分享react+three.js展示温湿度采集终端

前言

气象站将采集到的相关气象数据通过GPRS/3G/4G无线网络发送到气象站监测中心,摆脱了地理空间的限制。

前端:气象站主机将采集好的气象数据存储到本地,通过RS485等线路与GPRS/3G/4G无线设备相连。

通信:GPRS/3G/4G无线设备通过互联网与物联网云平台相连,气象站有计划的将收集到的气象信息通过无线设备发送到监控数据中心。

后台:气象监控中心通过互联网实现了对前端所有的自动气象站数据的采集和整合。

1、摆脱了地理空间的限制,可以在有无线信号的任何地方架设自动气象站点。

2、高规格工业级无线通信设备,有力的保证了气象数据的稳定可靠。

3、体积小巧、安装方便,使得现场安装调试人员轻松高效。

4、费用低廉,降低了运用成本。

温度、湿度等环境数据整合,趋势模拟。

温湿度采集终端

Pt100 就是说它的阻值在 0 度时为 100 欧姆, PT100 温度传感器。是一种以铂(Pt) 作成的电阻式温度传感器,属于正电阻系数, 其电阻和温度变化的关系式如下: R=Ro(1+α T)。广泛应用于实验室及工业环境。

技术参数

       存储温度:-10 ~ +55 °C、湿度 0~85%RH

       测量精度:温度: ±0.5°C ~ ±0.7°C

       显示分辨率: 0.1 C

       记录时间间隔:2秒~24小时

       存储:数据存储量 65000组数据

       电池电量:电池类型 1颗 2600mA 18650锂电池 

       电池寿命:3 年(测量速率在10秒/刷新 300秒/记录)

       尺寸:135mm×125mm×36mm

       材料/外壳: ABS工程塑料

PLC版

web简版

react+three.js,无三维建模软件,web三维展现温湿度采集器

应用程序的模块化理念,使用模块来构建你的代码。通过将实现隐藏在一个简单的接口后面,您可以使您的应用程序万无一失且易于使用。它只做它应该做的,没有别的 通过隐藏实现,我们对使用我们代码的人实施了良好的编码风格。您可以访问的实现越多,它就越有可能成为您以后必须处理的复杂的半生不熟的“修复”。创建3D场景时,唯一的限制是您的想象力 - 以及您的技术知识深度。要点是如何描述3D空间的坐标系和用于在坐标系内移动对象。场景图是一种用于描述构成我们场景的对象层次结构的结构,向量是用于描述3D空间中的位置(以及许多其他事物) ,还有不少于两种描述旋转的方式:欧拉角Euler angles和四元数quaternions

依赖

"react": "^18.2.0",

"three": "^0.162.0",

app.tsx

import React, { useEffect, useRef, useState } from 'react'
import './App.css';
import { World } from './World/World.js';interface appProps {style?: Record<string, unknown>;[key: string]: unknown;
}function App(props: appProps) {const { style, ...pros} = props;const renderRef = useRef(null);let  world: World;useEffect(() => {// eslint-disable-next-line @typescript-eslint/strict-boolean-expressionsif (renderRef && renderRef.current) {// Get a reference to the container element//const container = document.querySelector('#scene-container');//const container = document.getElementById('scene-container')// 1. Create an instance of the World app//world = new World(container);world = new World(renderRef.current);// 2. Render the scene// start the animation loopworld.start();}const timer = setInterval(() => {if(isAutoRotate){world.start();world.tick();}else{world.stop();}}, 1);return () => {cancelAnimationFrame(1);clearInterval(timer);};}, [renderRef])return (<div className="App"><header className="header"></header><main><div id="scene-container" ref={renderRef} style={{ position: 'relative', width: '100%', height: 'calc( 100vh - 100px )', ...style }} {...pros}></div></main><footer style={ { background: 'skyblue', height: '30px' }}></footer></div>)
}export default App;

world.js

/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/** @Date: 2024-03-21 14:57:52* @LastEditors: david* @LastEditTime: 2024-03-21 17:04:01* @FilePath: .\src\components\World.js* @Description: 创建三维场景单例*/
import { createCamera } from '../components/camera.js';
import { createCube } from '../components/cube.js';
import { createScene } from '../components/scene.js';
import { createControls } from '../components/controls.js';
import { createLights } from '../components/lights.js';import { createRenderer } from '../systems/renderer.js';
import { Resizer } from '../systems/Resizer.js';
import { Loop } from '../systems/Loop.js';// These variables are module-scoped: we cannot access them
// from outside the module 将相机、渲染器和场景创建为模块作用域变量
let camera;
let scene;
let light;
let renderer;
let controls;
let loop;
// 温湿度采集器
import { changeMaterial, updateData } from '../components/canvasTexture.js'/*** @description: 初始化三维场景 容器* @param {string} container - 三维场景挂载的div容器* @return {*}*/
class World {// 1. Create an instance of the World appconstructor(container) {// 首次使用构造器实例if (!(World.instance instanceof World)) {// 初始化相机camera = createCamera();// 初始化场景scene = createScene();// 初始化灯光light = createLights({directionX: 30,directionY: 10,directionZ: 0.5});model.scene.add(...light);// 初始化渲染器renderer = createRenderer();renderer.setSize(container.clientWidth, container.clientHeight);// Type: Element | Stringcontainer.appendChild(renderer.domElement);// container.innerHTML = null;loop = new Loop(camera, model.scene, renderer);// 初始化控制器controls = createControls(camera,renderer)//loop.updatables.push(controls);// 添加模型const cube = createCube();scene.add(cube);const  collectorCube = changeMaterial();// async await Promise resole reject Promise.all 解决异步加载模型和贴图collectorCube.then((res) => {scene.add(res);//loop.updatables.push(res);}).catch(err => {console.log('温湿度采集器添加失败:'+err)})// stop the cube's animationloop.updatables.push(cube);controls.addEventListener('change', () => {this.render();});const resizer = new Resizer(container, camera, renderer);resizer.onResize = () => {this.render();};this.render();this.animate();// 将this挂载到World这个类的instance属性上World.instance = this}return World.instance}// 2. Render the scenerender() {// draw a single frameif ((Boolean(renderer)) && (Boolean(scene)) && (Boolean(camera))) {renderer.render(scene, camera);}}animate(){try{// eslint-disable-next-line no-undef//requestAnimationFrame(this.animate);requestAnimationFrame(this.animate.bind(this));TWEEN.update();//更新控制器this.render()} catch (error) {// eslint-disable-next-line @typescript-eslint/strict-boolean-expressionsconsole.log(`Failed to add world imagery: ${error}`);}// eslint-disable-next-line @typescript-eslint/strict-boolean-expressionsif (controls) {controls.update();}}
}export { World };

camera.js

import { PerspectiveCamera, MathUtils } from 'three';function createCamera() {const camera = new PerspectiveCamera(45, // fov = Field Of View1, // aspect ratio (dummy value)0.1, // near clipping plane10000, // far clipping plane);// move the camera back so we can view the scene// camera.position.set(0, 0, 30);const layoutWidth = 25;const angle = camera.fov / 2;  // 夹角const rad = MathUtils.degToRad(angle);  // 转为弧度值const cameraZ = layoutWidth / 2 / Math.tan(rad);// 调整相机的 Z 轴位置,使桌台元素完整显示到场景camera.position.set(0, 15, cameraZ);return camera;
}export { createCamera };

scene.js

import { Color, Scene, Fog } from 'three';function createScene() {const scene = new Scene();scene.background = new Color(0xe6f4ff);scene.fog = new Fog( 0xa0a0a0, 5, 250 );return scene;
}export { createScene };

controls.js

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
function createControls ( Camera, renderer ) {// 轨道控制器const controls  = new OrbitControls(Camera, renderer.domElement);//设置控制器的中心点controls.target.set(0, 10, 0);const distanceZ = Camera.position.z;// 如果使用animate方法时,将此函数删除//controls.addEventListener( 'change', render );// 使动画循环使用时阻尼或自转 意思是否有惯性controls.enableDamping = false;//动态阻尼系数 就是鼠标拖拽旋转灵敏度// 阻尼系数controls.dampingFactor = 0.1;controls.minPolarAngle = Math.PI / 12;controls.maxPolarAngle = (Math.PI * 19) / 40;//是否可以缩放controls.enableZoom = true;//是否自动旋转controls.autoRotate = true;controls.autoRotateSpeed = 0.5;//设置相机距离原点的最远距离//controls.minDistance = 10;//设置相机距离原点的最远距离//controls.maxDistance = 200;controls.minDistance = distanceZ / 10;  // 相机离目标点的最小距离(放大)controls.maxDistance = distanceZ * 10;  // 相机离目标点的最大距离(缩小)//是否开启右键拖拽controls.enablePan = true;controls.tick = () => controls.update();return controls;
}export { createControls };

lights.js

import { HemisphereLight, AmbientLight, DirectionalLight, DirectionalLightHelper, SpotLight, SpotLightHelper } from 'three';function createLights({ directionX, directionY, directionZ }) {const hemisphere = new HemisphereLight(0xffffff, 0xffffff, 0.6);// move the light right, up, and towards ushemisphere.position.set(10, 10, 10);const ambient = new AmbientLight(0xffffff, 1);  // 环境光const spot = new SpotLight(0xfdf4d5);spot.position.set(5, directionY * 4, 0);spot.angle = Math.PI / 2;spot.power = 2000;// eslint-disable-next-line @typescript-eslint/no-unused-varsconst spotLightHelper = new SpotLightHelper(spot, 0x00f);const direct = new DirectionalLight(0xffffff, 3);  // 平行光direct.position.set(-directionX / 3, directionY * 4, directionZ * 1.5);direct.castShadow = true;direct.shadow.camera.left = -directionX;direct.shadow.camera.right = directionX;direct.shadow.camera.top = directionZ;direct.shadow.camera.bottom = -directionZ;// eslint-disable-next-line @typescript-eslint/no-unused-varsconst directLightHelper = new DirectionalLightHelper(direct, 1, 0xf00);return [hemisphere, ambient, spot, direct];}export { createLights };

cube.js

import { BoxGeometry, Mesh, //MeshBasicMaterial, MeshStandardMaterial, MathUtils  } from 'three';
function createCube() {// create a geometryconst geometry = new BoxGeometry(1, 1, 1);// create a default (white) Basic material// const material = new MeshBasicMaterial();// Switch the old "basic" material to// a physically correct "standard" materialconst spec = {color: 'purple',}const material = new MeshStandardMaterial(spec);// create a Mesh containing the geometry and materialconst cube = new Mesh(geometry, material);cube.position.set(0, 10, 0);// cube.rotation.set(-0.5, -0.1, 0.8);const radiansPerSecond = MathUtils.degToRad(30);// this method will be called once per framecube.tick = (delta) => {// increase the cube's rotation each framecube.rotation.z += radiansPerSecond * delta;cube.rotation.x += radiansPerSecond * delta;cube.rotation.y += radiansPerSecond * delta;};return cube;
}export { createCube };

loop.js

import { Clock } from "three";
const clock = new Clock();class Loop {constructor(camera, scene, renderer) {this.camera = camera;this.scene = scene;this.renderer = renderer;// somewhere in the Loop class:this.updatables = []}start() {this.renderer.setAnimationLoop(() => {// tell every animated object to tick forward one frame// this.tick();// render a framethis.renderer.render(this.scene, this.camera);});}stop() {this.renderer.setAnimationLoop(null);}tick(){// only call the getDelta function once per frame!const delta = clock.getDelta();// console.log(//   `The last frame rendered in ${delta * 1000} milliseconds`,// );// eslint-disable-next-line @typescript-eslint/strict-boolean-expressionsif(this.updatables.length){for (const object of this.updatables) {if(typeof object.tick == 'function'){object.tick(delta);}}}}
}export { Loop };

renderer.js

import { WebGLRenderer, PCFSoftShadowMap } from 'three';function createRenderer() {const renderer = new WebGLRenderer({ alpha: true, // 透明度antialias: true // 开启抗锯齿});// turn on the physically correct lighting modelrenderer.physicallyCorrectLights = true;renderer.shadowMap.enabled = true;renderer.shadowMap.type = PCFSoftShadowMap;renderer.setClearColor('#f8f8f6', 1);// eslint-disable-next-line no-undefrenderer.setPixelRatio(window.devicePixelRatio);return renderer;
}export { createRenderer };

resizer.js

const setSize = (container, camera, renderer) => {// Set the camera's aspect ratiocamera.aspect = container.clientWidth / container.clientHeight;// update the camera's frustumcamera.updateProjectionMatrix();// update the size of the renderer AND the canvasrenderer.setSize(container.clientWidth, container.clientHeight);// set the pixel ratio (for mobile devices)// eslint-disable-next-line no-undefrenderer.setPixelRatio(window.devicePixelRatio);
};class Resizer {constructor(container, camera, renderer) {// set initial size on loadsetSize(container, camera, renderer);// eslint-disable-next-line no-undefwindow.addEventListener("resize", () => {// set the size again if a resize occurssetSize(container, camera, renderer);// perform any custom actionsthis.onResize();});}// 空方法, 我们可以从Resizer类的外部自定义。// eslint-disable-next-line @typescript-eslint/no-empty-functiononResize() {}}export { Resizer };

canvasTexture.js

/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import { CanvasTexture, MeshLambertMaterial, BoxGeometry, Mesh,    } from 'three';
import moment from 'moment';
import collectorImg from '../assets/images/collector.png';
const meshcolor = 0xa1a5a9;
let cube;
let timeNow = new Date().valueOf();
let time = { hum: 40.0, tep: 20.0 };// 方法二:放大画布之后,需要把每一个绘制的 api 都乘以 dpr
// * 这样一来使用的时候就会很麻烦,所以我们需要把所有的绘制操作进行统一封装
// 可以参考这个库:https://github.com/jondavidjohn/hidpi-canvas-polyfill,不过这个库也不是所有 api 都覆盖
const adaptDPR = (canvas)=> { // 在初始化 canvas 的时候就要调用该方法const context = canvas.getContext('2d');const devicePixelRatio = window.devicePixelRatio || 1;const backingStoreRatio = context.webkitBackingStorePixelRatio ||context.mozBackingStorePixelRatio ||context.msBackingStorePixelRatio ||context.oBackingStorePixelRatio ||context.backingStorePixelRatio || 1;const ratiodpr = devicePixelRatio / backingStoreRatio;const { width, height } = canvas;// 重新设置 canvas 自身宽高大小和 css 大小。放大 canvas;css 保持不变,因为我们需要那么多的点// upscale the canvas if the two ratios don't matchif (devicePixelRatio !== backingStoreRatio) {canvas.width = width * ratiodpr;canvas.height = height * ratiodpr;canvas.style.width = width + 'px';canvas.style.height = height + 'px';// 注意这里没有用 scale// now scale the context to counter// the fact that we've manually scaled// our canvas element 通过backing store的像素比例和设备像素比(dpr)来控制你的图片和canvas是保证图片质量和清晰的保证。context.scale(ratiodpr, ratiodpr);}
}
// 每个涉及绘制的 api 时都乘以 dpr
// 获取带数据的canvas
const getTextCanvas = async ({ tep, hum }) => {const time = moment().format('HH:mm:ss');const width = 310, height = 173;const canvas = document.createElement('canvas');canvas.width = width;canvas.height = height;adaptDPR(canvas);const ctx = canvas.getContext('2d');return new Promise((resole) => {if (ctx) {const img = new Image();img.src = collectorImg;//图片加载完后,将其显示在canvas中img.onload = () => {ctx.drawImage(img, 0, 0, width, height);ctx.font = 18 + 'px " bold';ctx.fillStyle = '#333';ctx.textAlign = 'center';ctx.textBaseline = 'middle';// 实时温度ctx.fillText(tep, width * 0.33, height * 0.44);// 实时湿度ctx.fillText(hum, width * 0.33, height * 0.70);// 数据采集时间ctx.font = 10 + 'px " bold';ctx.fillText(time, width * 0.24 , height * 0.245);resole(canvas);};}});
}// 改变材质种类
const changeMaterial = async () => {const canvas = await getTextCanvas({ hum: 40, tep: 20 });if (canvas) {const texture = new CanvasTexture(canvas);const materials = [new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),new MeshLambertMaterial({color: meshcolor,opacity: 1,transparent: true,map: texture,}),new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),];const geometry = new BoxGeometry(8.404, 6.16, 1);cube = new Mesh(geometry, materials);cube.position.set(0, 15, 0);//scene.add(cube);return cube;}
}const updateData = async () => {if (new Date().valueOf() - timeNow > 500) {timeNow = new Date().valueOf();changeValues();}const canvas = await getTextCanvas(time);if (canvas && cube) {cube.material[4].map = new CanvasTexture(canvas);cube.material.map.needsUpdate = true;}
}// 更新time数据
const changeValues = () => {const hum = parseFloat((39 + Math.random() * 10).toFixed(1));const tep = parseFloat((19 + Math.random() * 5).toFixed(1));setTime({ hum: hum, tep: tep})
}const setTime = (date)=>{time = date
}export {changeMaterial,updateData
}

采集器正面贴图,空出需要动态渲染的时间、温度、湿度,采集器用用最简单的长方形盒子代替。

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement
);root.render(<React.StrictMode><App /></React.StrictMode>
);

index.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta name="theme-color" content="#000000" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta name="google-site-verification" content="FTeR0c8arOPKh8c5DYh_9uu98_zJbaWw53J-Sch9MTg"><meta data-rh="true" name="keywords" content="React three.js World示例"><meta data-rh="true" name="description" content="React three.js World示例"><meta data-rh="true" property="og:title" content="React three.js World示例"><link rel="icon" href="./favicon.ico"><title>React three.js World示例</title></head><body><div id="root"></div></body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/293694.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络链路层

数据链路 链路是从一个节点到相邻节点之间的物理线路&#xff08;有线或无线&#xff09; 数据链路是指把实现协议的软件和硬件加到对应链路上。帧是点对点信道的数据链路层的协议数据单元。 点对点信道 通信的主要步骤&#xff1a; 节点a的数据链路层将网络层交下来的包添…

Dockerfile和Docker-compose

一、概述 Dockerfile和Docker Compose是用于构建和管理 Docker 容器的两个工具&#xff0c;但它们的作用和使用方式不同。 Dockerfile Dockerfile 是一个文本文件&#xff0c;用于定义 Docker 镜像的构建规则。它包含一系列指令&#xff0c;如 FROM&#xff08;指定基础镜像…

【蓝桥杯第十三届省赛B组】(详解)

九进制转十进制 #include <iostream> #include<math.h> using namespace std; int main() {cout << 2*pow(9,3)0*pow(9,2)2*pow(9,1)2*pow(9,0) << endl;return 0; }顺子日期 #include <iostream> using namespace std; int main() {// 请在此…

安全SCDN的威胁情报库对DDOS防护有什么好处

目前网络攻击事件频频发生&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击已成为各种企业&#xff08;小到区域性小公司大到各种跨国公司&#xff09;的主要威胁&#xff0c;DDoS 攻击可能会对企业造成重大损害和破坏&#xff0c;比如对目标公司的业务造成产生不利…

吴晓波频道:构建知识付费领域的数据飞轮

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 知识付费正在完成新阶段的转变。 知识付费的概念可以追溯到 20 世纪 80 年代的彼得德鲁克&#xff0c;他在《后资本主义》一书中提出“知识经济”&#xff0c;指出…

IDEA跑Java后端项目提示内存溢出

要设置几个地方&#xff0c;都试一下吧&#xff1a; 1、默认是700&#xff0c;我们设置大一点&#xff08;上次配置了这儿就解决了&#xff09; 2、 3、 4、-Xmx4g

redolog 和 binlog 的区别以及两阶段提交

最近在学习MySQL架构的时候&#xff0c;关于执行器&#xff0c;存储引擎的具体操作那里&#xff0c;有些地方不是很懂&#xff0c;我仔细思考了一下&#xff0c;发现我对两阶段提交这个过程比较模糊&#xff0c;所以我特意写一篇文章来说一下两阶段提交。 比如说一条更新语句&…

接口自动化框架搭建(九):接入钉钉消息通知

1&#xff0c;jenkins安装钉钉插件 2&#xff0c;在钉钉群聊设置机器人 3&#xff0c;jenkins配置钉钉 根据情况选择&#xff1a; 除了这些&#xff0c;其他不用配置&#xff0c;配置完成点击确认 4&#xff0c;项目配置 添加后保存 5&#xff0c;测试下效果 构建完成后&a…

免费开源的 AI 绘图工具 ImgPilot

免费开源的 AI 绘图工具 ImgPilot 分类 开源分享 项目名: ImgPilot -- 通过提示词及涂鸦生成图片 Github 开源地址&#xff1a; GitHub - leptonai/imgpilot: Turn the draft into amazing artwork with the power of Real-Time Latent Consistency Model 在线地址&#xff…

Go语言学习Day6:数组与切片

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1. 数组① 什么是数组② 数组的声明③ 初始化数组的几种方式④ 遍历数组元素⑤ 数组为值类型⑥ 数…

Excel 粘贴回筛选后的单元格不能完全粘老是少数据 ,有些单元格还是空的

环境&#xff1a; excel2021 Win10专业版 问题描述&#xff1a; excel 粘贴回筛选后的单元格不能完全粘老是少数据 有些单元格还是空的 复制选择筛选后A1-A10单元格 &#xff0c;定位条件&#xff09;&#xff08;仅可见单元格&#xff09;来访问&#xff0c;或者你可以使用…

牛角工具箱源码 轻松打造个性化在线工具箱

&#x1f389; Whats this&#xff1f; 这是一款在线工具箱程序&#xff0c;您可以通过安装扩展增强她的功能 通过插件模板的功能&#xff0c;您也可以把她当做网页导航来使用~ 觉得该项目不错的可以给个Star~ &#x1f63a; 演示地址 https://tool.aoaostar.com &#x1f…

MySQL 高级语句(一)

一、MySQL查询 1.1 排序 1.1.1 排序语法 1.1.2 order by案例 1.2 区间判断及查询不重复记录 1.2.1 区间判断 1.2.2 查询不重复记录 1.3 对结果进行分组 1.3.1 group by 语法 1.3.2 group by 案例 1.4 限制结果条目 1.4.1 LIMIT 语法 1.4.2 LIMIT 案例 1.5 设置别名…

分治——归并排序算法

例题一 解法&#xff08;归并排序&#xff09;&#xff1a; 算法思路&#xff1a; 归并排序的流程充分的体现了「分⽽治之」的思想&#xff0c;⼤体过程分为两步&#xff1a; ◦ 分&#xff1a;将数组⼀分为⼆为两部分&#xff0c;⼀直分解到数组的⻓度为 1 &#xff0c;使…

网络游戏推广利器:Xinstall一站式解决方案

随着网络游戏的飞速发展&#xff0c;游戏推广已成为游戏公司不可或缺的一环。然而&#xff0c;面对渠道繁多、效果评估困难、用户获取成本高昂等问题&#xff0c;许多游戏公司在推广过程中感到力不从心。今天&#xff0c;我们要为大家介绍一款强大的游戏推广利器——Xinstall。…

[leetcode] 100. 相同的树

给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true示例 2&a…

Linux 理解进程信号

目录 一、共享内存通信机制中的临界资源访问与同步控制 1、概念 2、生活角度理解信号机制 3、信号量的操作 二、信号 1、生活角度的信号 2、技术应用角度的信号 3、操作系统角度的信号 信号如何产生 理解组合键变为信号 理解信号如何被进程保存 时钟中断&#xff0…

基于《2023腾讯云容器和函数计算技术实践精选集》—探索腾讯云TKE的Docker容器、Serverless和微服务优势

重剑无锋&#xff0c;大巧不工。 ——金庸 腾讯云TKE&#xff0c;全称Tencent Kubernetes Engine&#xff0c;是一种完全托管式的容器服务。它可以帮助用户快速、高效地部署和管理Kubernetes集群&#xff0c;并提供一系列与之相关的云服务&#xff0c;如负载均衡、云硬盘、对象…

汇编语言第四版-第3章 寄存器(内访问)

al为ax的低字节&#xff0c;ax寄存器为累加器。

Vue element-plus 导航栏 [el-menu]

导航栏 [el-menu] Menu 菜单 | Element Plus el-menu有很多属性和子标签&#xff0c;为网站提供导航功能的菜单。 常用标签&#xff1a; 它里面有两个子标签。el-menu-item&#xff0c;它其实就是el-menu每一个里面的item&#xff0c;item就是真实匹配到路由的每个栏目&#…