当前位置: 首页 > news >正文

Three.js机器人与星系动态场景:实现3D渲染与交互式控制

内容摘要:使用Three.js库构建了一个交互式的3D场景。组件中创建了一个机器人模型,包括头部、眼睛、触角、身体和四肢,以及两个相同的机器人实例以实现动态效果。场景中还加入了粒子效果,模拟星系环境,增强了视觉效果。通过OrbitControls,用户可以对机器人进行旋转控制。组件在渲染时会根据用户界面的变化动态调整渲染,并在指定的div容器中显示。整体上,这个组件提供了一个基础的3D动画展示和用户交互的框架。

  1. 在React中集成Three.js库,创建一个动态渲染的3D场景。
  2. 定义和渲染多个Three.js几何体,如机器人身体、胳膊、腿、眼睛和触角。
  3. 添加交互性,如旋转和轨道控制器,以提供更好的用户体验。
  4. 创建粒子特效,模拟星系环境,与机器人形成对比。

 一、项目搭建react+three.js

实现这样的效果需要安装three.js包;至于使用vue还是react框架都行,因为three.js只需要一个div作为挂载点即可。也用不到框架的细节。本文以react为例实现。

 依次执行以下命令,完成react项目的初始化和threejs的安装

 

 

良好的编码习惯要求我们,在views里新增一个robot文件夹,根据react组件的特效,用.tsx后缀表示是组件。定义一个方法名为Robot的function并将其默认导出。react的特点,函数式组件。方法名就是组件名,这个是react内部进行编译处理的。跟vue差别很大。

 ​​​

 在App.tsx中引入robot组件

 npm run start 运行即可看到效果

 

 二、实现细节

实现机器人及星空特效,其中机器人构建可以是批量的,机器人身体又可以拆分为脑袋、触角、眼睛、身体、胳膊、腿等细节。每个部分单独用有方法实现,逻辑拆分清晰。

 对单个3D模型来说,需要三个东西:mesh=geometry(几何)+material(材料)

  1. 几何体(Geometry):

    • THREE.SphereGeometry: 用于创建球形几何体。它接受几个参数,包括半径(radius)、宽度分段(widthSegments)、高度分段(heightSegments)、水平起始角度(phiStart)、水平扫描角度(phiLength)、垂直起始角度(thetaStart)和垂直扫描角度(thetaLength)。
    • THREE.CapsuleGeometry: 用于创建胶囊形状的几何体,可以看作是一个圆柱体两端加上半球体。它接受两个参数,分别是半径(radius)和高度(height)。
    • THREE.CylinderGeometry :创建圆柱体。圆柱体由两个圆形底面和一个侧面组成。这个类的作用是定义一个圆柱形状的3D几何体,它可以在 Three.js 的场景中被渲染。
  2. 材质(Material):

    • THREE.MeshStandardMaterial: 用于创建标准网格材质,它提供了多种物理渲染特性,如颜色(color)、粗糙度(roughness)和金属度(metalness)等。
  3. 网格(Mesh):

    • THREE.Mesh: 网格是几何体和材质的组合,可以通过它将几何体渲染到场景中。它接受一个几何体(geometry)和一个材质(material)作为参数。

这里方便解耦,单个方法只生成模型,在调用方法的地方确定模型的位置。

 机器人脑袋

//机器人脑袋
function createHead() {//SphereGeometry创建球形几何体const head = new THREE.SphereGeometry(4, 32, 16, 0, Math.PI * 2, 0, Math.PI * 0.5);const headMaterial = new THREE.MeshStandardMaterial({color: 0x43b988,roughness: 0.5,metalness: 1.0,});const headMesh = new THREE.Mesh(head, headMaterial);return headMesh;
}

机器人触角 

//触角
function generateHorn(y: number, z: number, angle: number) {//触角 CapsuleGeometry 创建胶囊形状的几何体。胶囊形状可以看作是一个圆柱体两端加上半球体const line = new THREE.CapsuleGeometry(0.1, 2);const lineMaterial = new THREE.MeshStandardMaterial({color: 0x43b988,roughness: 0.5,metalness: 1.0,});const lineMesh = new THREE.Mesh(line, lineMaterial);lineMesh.position.y = y;lineMesh.position.z = z;lineMesh.rotation.x = angle;return lineMesh;
}

机器人眼睛 

//机器人眼睛
function generateEye(x: number, y: number, z: number) {//SphereGeometry创建球形几何体const eye = new THREE.SphereGeometry(0.5, 32, 16, 0, Math.PI * 2, 0, Math.PI * 2);const eyeMaterial = new THREE.MeshStandardMaterial({color: 0x212121,roughness: 0.5,metalness: 1.0,});const eyeMesh = new THREE.Mesh(eye, eyeMaterial);eyeMesh.position.x = x;eyeMesh.position.y = y;eyeMesh.position.z = z;return eyeMesh;
}

机器人身体 

//机器人身体
function generateBody() {//CylinderGeometry第一个参数是上部分圆的半径,第二个参数是下部分圆的半径,第三个参数是高度,材质使用的跟腿一样const body = new THREE.CylinderGeometry(4, 4, 6);const bodyMaterial = new THREE.MeshStandardMaterial({color: 0x43b988,roughness: 0.5,metalness: 1.0,});const bodyMesh = new THREE.Mesh(body, bodyMaterial);return bodyMesh;
}

机器人胳膊 

//胳膊、腿
function generateLegs(y: number, z: number) {const leg1 = new THREE.CapsuleGeometry(1, 4);const legMaterial1 = new THREE.MeshStandardMaterial({color: 0x43b988,roughness: 0.5,metalness: 1.0,});const leg1Mesh = new THREE.Mesh(leg1, legMaterial1);leg1Mesh.position.y = y;leg1Mesh.position.z = z;return leg1Mesh;
}

创建机器人 

//创建机器人
function generateRobot() {// 创建一个Three.js对象,用于存放机器人const robot = new THREE.Object3D();const headMesh = createHead();headMesh.position.y = 6.5;robot.add(headMesh);//眼睛const leftEye = generateEye(3, 8, -2);const rightEye = generateEye(3, 8, 2);robot.add(leftEye);robot.add(rightEye);const leftHorn = generateHorn(11, -1, (-Math.PI * 30) / 180);const rightHorn = generateHorn(11, 1, (Math.PI * 30) / 180);robot.add(leftHorn);robot.add(rightHorn);const body = generateBody();body.position.y = 4;robot.add(body);// 生成机器人左腿robot.add(generateLegs(0, -2));// 生成机器人右腿robot.add(generateLegs(0, 2));//胳膊robot.add(generateLegs(3, 5));robot.add(generateLegs(3, -5));//物体缩放robot.scale.x = 0.3;robot.scale.y = 0.3;robot.scale.z = 0.3;return robot;
}

生成粒子场景 

//创建粒子星星
function generateStarts(num: number) {//制作粒子特效const starts = new THREE.Object3D();const obj = new THREE.SphereGeometry(0.2, 3, 3);const material = new THREE.MeshStandardMaterial({color: 0x43b988,roughness: 0.5,metalness: 5,});const mesh = new THREE.Mesh(obj, material);for (let i = 0; i < num; i++) {const target = new THREE.Mesh();target.copy(mesh);target.position.x = Math.floor(Math.random() * 18 + Math.floor(Math.random() * -18));target.position.y = Math.floor(Math.random() * 18 + Math.floor(Math.random() * -18));target.position.z = Math.floor(Math.random() * 18 + Math.floor(Math.random() * -18));starts.add(target);}return starts;
}

 主方法

Scene场景

scene是一个THREE.Scene对象,它是Three.js中场景的容器,用于组织和管理3D对象,如几何体、材质、相机和灯光等。

  • add(object): 这个方法用于将对象(例如机器人、光源、粒子等)添加到场景中。

示例代码中使用了多次:

scene.add(robot);
scene.add(robot2);
scene.add(straightLight);
scene.add(starts);

PerspectiveCamera透视相机

3D场景中的相机视角。一般都是使用透视相机PerspectiveCamera,第一个参数是fov,表示相机所成的一个四棱台远面与近面之间的夹角,夹角越小,看见的东西越少,夹角越大,看见的东西就越多,但是周围会显的比较模糊,一般取值以45~75最佳,第二个参数aspect是近裁面的一个宽高比,我们用窗口的宽除以窗口的高就可以了,第三个值near与第四个值far分别是与近面和远面的距离,这里设置的值分别为0.1与1000,调用camera.positon.set表示设置相机的位置,默认都是在(0,0,0)的位置,我们这里给相机设置的位置为(15,12,8),并且让相机正对(0,0,0)的位置

  • PerspectiveCamera是Three.js中的透视投影相机,文中使用的参数解释如下:
    • 75:视角(Field of View,FOV),决定了视场的宽度,单位是度。
    • window.innerWidth / window.innerHeight:纵横比,根据浏览器窗口的宽度和高度计算,确保相机适应窗口大小。
    • 0.1:近裁剪面(Near clipping plane),即相机能看到的最近物体的距离。
    • 1000:远裁剪面(Far clipping plane),即相机能看到的最远物体的距离。

DirectionalLight光源

在Three.js中,DirectionalLight 是一种光源,它模拟从特定方向发出的平行光,类似于太阳光。这种光源的特点是所有从光源发出的光线都是平行的,不会随着距离的增加而发散。

DirectionalLight 在这里的作用包括:

  1. 照亮场景:它为场景提供光照,使得场景中的物体可以被看到,并根据材质属性产生不同的光照效果。

  2. 产生阴影DirectionalLight 可以产生阴影效果,使得场景更加真实。物体遮挡光线的地方会形成阴影,有助于表现物体的立体感和空间位置。

  3. 定义光照方向:通过设置 DirectionalLight 的位置和方向,可以定义光线照射到场景的角度,从而影响场景的整体光照效果。

  4. 调整光照强度:可以通过设置 intensity 属性来调整光线的亮度。

OrbitControls 控制器

Three.js 中的 OrbitControls 是一个控制器,它允许用户通过鼠标或触摸事件来控制相机的移动,从而实现对场景的旋转、缩放和平移操作。这个控制器使得用户可以更自然地与3D场景交互。

在使用 OrbitControls 时,需要注意以下几点:

  • 控制器需要与相机和渲染器的DOM元素一起被初始化。
  • 在动画循环中调用 controls.update() 方法来确保控制器可以更新相机状态。
  • 可以通过修改 OrbitControls 的各种属性来自定义控制行为,例如最小/最大缩放距离、旋转限制等。

OrbitControls 是Three.js中非常实用的一个工具,它大大简化了3D场景的用户交互开发过程。

以下是 OrbitControls 的一些主要作用:

  1. 旋转(Rotate):用户可以通过拖动鼠标来旋转相机,从而改变视角。

  2. 缩放(Zoom):通过滚动鼠标滚轮或触摸屏幕进行捏合操作,可以放大或缩小场景。

  3. 平移(Pan):通过按下鼠标右键并拖动,或者在某些触摸设备上通过特定的手势,可以在场景中平移相机。

以下是 OrbitControls 的基本用法:

// 引入OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// 设置相机位置
camera.position.set(0, 0, 5);// 创建OrbitControls实例并传入相机和渲染器
const controls = new OrbitControls(camera, renderer.domElement);// 创建一些对象添加到场景中
// ...// 渲染场景
function animate() {requestAnimationFrame(animate);controls.update(); // 更新控制器renderer.render(scene, camera);
}
animate();

position 位置信息

在 Three.js 中,position 属性的作用是用于确定 3D 对象在场景中的位置, 属性对于实现 3D 场景中对象的布局、动画和交互等方面都非常重要。通过设置对象的 position 属性,可以精确地指定该对象在三维空间中的坐标。这使得能够将对象放置在所需的位置,从而构建出具有特定布局和结构的 3D 场景。

例如,如果要将一个立方体放置在场景的特定点(比如 x 坐标为 10,y 坐标为 20,z 坐标为 30),可以这样设置:

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);cube.position.set(10, 20, 30);scene.add(cube);

这样,立方体就会出现在指定的位置上。 

rotation旋转属性

在 Three.js 中,rotation 属性的作用是用于确定 3D 对象在场景中的旋转状态。通过设置对象的 rotation 属性,可以精确地指定该对象在三维空间中的旋转角度。这使得能够将对象旋转到所需的方向,从而构建出具有特定朝向和视角的 3D 场景。

rotation 属性使用的是欧拉角(Euler angles),它包括三个分量:xy 和 z,分别表示绕 X 轴、Y 轴和 Z 轴的旋转角度(以弧度为单位)。

例如,如果要将一个立方体绕 Y 轴旋转 45 度(即 π/4 弧度),可以这样设置:

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);cube.rotation.y = Math.PI / 4; // 45 degrees in radiansscene.add(cube);

requestAnimationFrame实现动画 

使用requestAnimationFrame: requestAnimationFrame是浏览器提供的API,用于在每一帧绘制动画。Three.js中的动画通常通过这个API来实现。

function animate() {requestAnimationFrame(animate);// 更新对象属性,例如位置、旋转等cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 渲染场景renderer.render(scene, camera);
}
animate();

useEffect 

在React组件中,useEffect 钩子用于处理副作用操作,比如数据获取、订阅、手动更改DOM等。useEffect 钩子的主要作用是在组件挂载后将 Three.js 渲染器的 DOM 元素添加到指定的容器中,并在组件卸载时进行清理。

  1. 组件挂载时添加渲染器 DOM 元素

    • useEffect 钩子在组件挂载时执行,确保 containerRef.current 已经指向了实际的 DOM 元素。
    • 通过 containerRef.current.appendChild(renderer.domElement),将 Three.js 渲染器的 DOM 元素添加到指定的容器中。
  2. 确保渲染器 DOM 元素正确添加

    • 如果不使用 useEffect,直接在组件渲染时添加渲染器 DOM 元素,可能会导致 containerRef.current 为 null,因为此时 DOM 元素可能还未挂载到页面上。
/*** 创建一个Three.js场景,包括相机和渲染器*/
function Robot() {// 创建一个div容器,用于存放渲染的Three.js场景const containerRef = useRef<HTMLDivElement>(null);const scene = new THREE.Scene();// 创建一个Three.js相机,包括透视投影、宽高比、近裁剪面和远裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(15, 12, 8);camera.lookAt(0, 0, 0);// 创建一个Three.js渲染器,包括抗锯齿const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);const robot = generateRobot();const robot2 = generateRobot();robot2.position.x = 6;robot2.position.z = 6;// 将机器人身体添加到场景中scene.add(robot);scene.add(robot2);// 创建一个Three.js方向光,包括颜色、强度const straightLight = new THREE.DirectionalLight(0xffffff, 5);// 设置方向光的位置straightLight.position.set(5, 5, 10);// 将方向光添加到场景中scene.add(straightLight);const starts = generateStarts(200);scene.add(starts);//轨道控制器const controls = new OrbitControls(camera, renderer.domElement);controls.update();const update = () => {requestAnimationFrame(update);robot.rotation.y -= 0.005; //机器人旋转robot2.rotation.y -= 0.005;// 粒子旋转starts.rotation.y -= 0.001;starts.rotation.z += 0.001;starts.rotation.x += 0.001;renderer.render(scene, camera);};update(); //自动更新// 监听组件挂载和卸载useEffect(() => {// 如果div存在,将渲染器dom元素添加到div中if (containerRef.current) {containerRef.current.appendChild(renderer.domElement);// 渲染场景renderer.render(scene, camera);}}, [containerRef]);// 返回div容器,用于存放渲染的Three.js场景return <div ref={containerRef} style={{ width: "100vw", height: "100vh" }}></div>;
}

相关文章:

Three.js机器人与星系动态场景:实现3D渲染与交互式控制

内容摘要&#xff1a;使用Three.js库构建了一个交互式的3D场景。组件中创建了一个机器人模型&#xff0c;包括头部、眼睛、触角、身体和四肢&#xff0c;以及两个相同的机器人实例以实现动态效果。场景中还加入了粒子效果&#xff0c;模拟星系环境&#xff0c;增强了视觉效果。…...

Android系统集成和使用FFmpeg

文章目录 前言FFmpeg源码下载交叉编译NDK下载x264编译源码下载编译 FFmpeg编译脚本 AOSP继承FFmpeg 前言 原生AOSP中并未继承FFmpeg&#xff0c;所以要想在android上使用&#xff0c;需要自己编译集成。 FFmpeg源码下载 git clone https://git.ffmpeg.org/ffmpeg.git目前最新…...

水果商城外卖微信小程序模板

手机微信水果外卖&#xff0c;水果电商&#xff0c;水果商城网页小程序模板。包含&#xff1a;主页、列表页、详情页、购物车、个人中心。 水果商城外卖小程序模板...

【前端】面试八股文——输入URL到页面展示的过程

【前端】面试八股文——输入URL到页面展示的过程 1. DNS解析 当用户在浏览器中输入URL并按下回车时&#xff0c;首先需要将域名转换为IP地址&#xff0c;这个过程称为DNS&#xff08;域名系统&#xff09;解析。具体步骤如下&#xff1a; 浏览器缓存&#xff1a;浏览器首先检…...

什么是应用安全态势管理 (ASPM):综合指南

软件开发在不断发展&#xff0c;应用程序安全也必须随之发展。 传统的应用程序安全解决方案无法跟上当今开发人员的工作方式或攻击者的工作方式。 我们需要一种新的应用程序安全方法&#xff0c;而ASPM在该方法中发挥着关键作用。 什么是 ASPM&#xff1f; 应用程序安全…...

认识100种电路之耦合电路

在电子电路的世界中&#xff0c;耦合电路宛如一座精巧的桥梁&#xff0c;连接着各个功能模块&#xff0c;发挥着至关重要的作用。 【为什么电路需要耦合】 在复杂的电子系统中&#xff0c;不同的电路模块往往需要协同工作&#xff0c;以实现特定的功能。然而&#xff0c;这些模…...

c++【入门】三数的乘积

限制 时间限制 : 1 秒 内存限制 : 128 MB 题目 你已经学了一些程序的输入&#xff0c;这次&#xff0c;你需要在没有老师的任何帮助下完成这次的任务啦。这次任务&#xff0c;我们要读入三个整数&#xff0c;并且计算它们的乘积。 这是一个非常简单的题目&#xff0c;意在…...

C++实现简化版Qt的QObject(4):增加简单实用的事件机制

前面的文章已经实现了许多QObject的功能了&#xff1a; C实现一个简单的Qt信号槽机制 C实现简化版Qt信号槽机制&#xff08;2&#xff09;&#xff1a;增加内存安全保障 C实现简化版Qt的QObject&#xff08;3&#xff09;&#xff1a;增加父子关系、属性系统 但是&#xff0c;…...

JTracker IDEA 中最好的 MyBatis 日志格式化插件

前言 如果你使用 MyBatis ORM 框架&#xff0c;那么你应该用过 MyBatis Log 格式化插件&#xff0c;它可以让我们的程序输出的日志更人性化。 但是有一个问题&#xff0c;通常我们只能看到格式化后的效果&#xff0c;没办法知道这个 SQL 是谁执行的以及调用的链路。 如下图所…...

物联网工业级网关解决方案 工业4G路由器助力智慧生活

随着科技的飞速发展&#xff0c;无线通信技术正逐步改变我们的工作与生活。在这个智能互联的时代&#xff0c;一款高性能、稳定可靠的工业4G路由器成为了众多行业不可或缺的装备。工业4G路由器以其卓越的性能和多样化的功能&#xff0c;助力我们步入智慧新纪元。 一、快速转化&…...

IoTDB Committer+Ratis PMC Member:“两全其美”的秘诀是?

IoTDB & Ratis 双向深耕&#xff01; 还记得一年前我们采访过拥有 IoTDB 核心研发 Ratis Committer “双重身份”的社区成员宋子阳吗&#xff1f;&#xff08;点此阅读&#xff09; 我们高兴地发现&#xff0c;一年后&#xff0c;他在两个项目都更进一步&#xff0c;已成为…...

【链表】- 移除链表元素

1. 对应力扣题目连接 移除链表元素 2. 实现案例代码 public class RemoveLinkedListElements {public static void main(String[] args) {// 示例 1ListNode head1 new ListNode(1, new ListNode(2, new ListNode(6, new ListNode(3, new ListNode(4, new ListNode(5, new …...

云原生之使用Docker部署RabbitMQ消息中间件

云原生之使用Docker部署RabbitMQ消息中间件 一、RabbitMQ介绍1.1 RabbitMQ简介1.2 RabbitMQ特点1.3 RabbitMQ使用场景 二、检查Docker环境2.1 检查Docker版本2.2 检查操作系统版本2.3 检查Docker状态 三、下载RabbitMQ镜像四、部署RabbitMQ服务4.1创建挂载目录4.2 运行RabbitMQ…...

opengl箱子的显示

VS环境配置&#xff1a; /JMC /ifcOutput "Debug\" /GS /analyze- /W3 /Zc:wchar_t /I"D:\Template\glfwtemplate\glfwtemplate\assimp" /I"D:\Template\glfwtemplate\glfwtemplate\glm" /I"D:\Template\glfwtemplate\glfwtemplate\LearnOp…...

Oracle 视图、存储过程、函数、序列、索引、同义词、触发器

优质博文&#xff1a;IT-BLOG-CN 一、视图 从表中抽出的逻辑上相关的数据集合&#xff0c;视图是一种虚表&#xff0c;视图是建立在已有表的基础之上&#xff0c;视图赖以建立的这些表称为基表。向视图提供数据的是 SELECT语句&#xff0c;可以将视图理解为存储起来的SELECT语…...

网站被浏览器提示“不安全”的解决办法

在互联网时代&#xff0c;网站的安全性直接关系到用户体验和品牌形象。当用户访问网站时&#xff0c;如果浏览器出现“您与此网站之间建立的连接不安全”的警告&#xff0c;这不仅会吓跑潜在客户&#xff0c;还可能对网站的SEO排名造成等负面影响。 浏览器发出的“不安全”警告…...

typescript定义函数的传参、返回值

Render 函数中定义函数传参 interface List {id: number;name: string; }interface Result {data: List[]; //表示由 List 接口组成的数组 }function Render(result: Result) {result.data.forEach(value > {console.log(value);}); }let result {data: [{id: 1,name: 张三…...

GlimmerHMM安装与使用-生信工具24

GlimmerHMM 01 概述 GlimmerHMM是一种基于广义隐马尔科夫模型&#xff08;GHMM&#xff09;的新型基因预测工具。虽然该基因预测工具符合GHMM的总体数学框架&#xff0c;但它还结合了从GeneSplicer程序中改编的剪接位点模型。可变长度的特征状态&#xff08;例如外显子、内含…...

Elasticsearch架构基本原理

Elasticsearch的架构原理可以详细分为以下几个方面进行介绍&#xff1a; 一、Elasticsearch基本概念 Elasticsearch&#xff08;简称ES&#xff09;是一个基于Lucene构建的开源、分布式、RESTful搜索和分析引擎。它支持全文搜索、结构化搜索、半结构化搜索、数据分析、地理位…...

STM32自己从零开始实操08:电机电路原理图

一、LC滤波电路 其实以下的滤波都可以叫低通滤波器。 1.1倒 “L” 型 LC 滤波电路 1.1.1定性分析 1.1.2仿真实验 电感&#xff1a;通低频阻高频的。仿真中高频信号通过电感&#xff0c;因为电感会阻止电流发生变化&#xff0c;故说阻止高频信号 电容&#xff1a;隔直通交。…...

C++ 17 正则表达式

正则表达式不是C语言的一部分&#xff0c;这里仅做简单的介绍。 将这项技术引进&#xff0c;在 』的讨论 正则表达式描述了一种字符串匹配的模式。一般使用正则表达式主要是实现下面三个需求&#xff1a; 1,检查一个串是否包含某种形式的子串&#xff1b; 2,将匹配的子串替换&a…...

ios tableview吸顶

由于项目需要实现一个上滑吸顶的效果&#xff0c;网上也看到有很多种方式实现&#xff0c;但是如果加上下拉刷新的功能会导致界面异常&#xff0c;还有第三方库实现方式库&#xff0c;太繁琐了&#xff0c;下面是我的实现方式&#xff0c;效果如下&#xff1a; tablevie滑动吸顶…...

编译rustdesk,使用flutter、hwcodec硬件编解码、支持Windows 7系统

目录 安装相应的环境安装visual studio安装vpkg安装rust开发环境安装llvm和clang编译源码下载源码使用Sciter作为UI的(已弃用)使用flutter作为UI的(主流)下载flutter sdk桥接静默安装支持Windows 7系统最近某desk免费的限制越来越多,实在没办法,平时远程控制用的比较多,…...

OpenCv高阶(十九)——dlib关键点定位

文章目录 一、什么是人脸关键点定位&#xff1f;二、关键点模型的下载及关键信息的理解三、dlib关键点定位的简单实现&#xff08;1&#xff09;导入必要的库&#xff08;2&#xff09;从指定路径读取图像文件&#xff08;3&#xff09;创建dlib的正面人脸检测器对象&#xff0…...

内存管理--《Hello C++ Wrold!》(8)--(C/C++)--深入剖析new和delete的使用和底层实现

文章目录 前言C/C内存分布new和deletenew和delete的底层定位new表达式 内存泄漏作业部分 前言 在C/C编程中&#xff0c;内存管理是理解程序运行机制的核心基础&#xff0c;也是开发高效、稳定程序的关键。无论是局部变量的存储、动态内存的分配&#xff0c;还是对象生命周期的…...

mysql分布式教程

MySQL 主从复制 主从复制原理&#xff1a;MySQL 主从复制是指数据可以从一个 MySQL 数据库服务器主节点复制到一个或多个从节点。主库将写操作记录在二进制日志文件中&#xff0c;从库的 IO 线程请求读取主库的二进制日志并写入中继日志&#xff0c;然后 SQL 线程执行中继日志中…...

[SC]sc_signal_rv的用法和sc_signal相比有什么优势?

sc_signal_rv的用法和sc_signal相比有什么优势? 在 SystemC 中,sc_signal<T> 是最常用的单驱动(single‐driver)信号通道;而 sc_signal_rv<W>(“rv” = resolved vector)则是一种多驱动、带总线(tri-state)分辨功能的信号。下面分几点来说明它们的…...

sl4j+log4j日志框架

sl4jlog4j日志框架 slf4j (Simple Loging Facade For Java) 即它仅仅是一个为 Java 程序提供日志输出的统一接口&#xff0c;并不是一个具体的日志实现方案&#xff0c;所以单独的 slf4j 是不能工作的&#xff0c;必须搭配其他具体的日志实现方案&#xff08;例如&#xff1a;…...

MyBatisPlus--条件构造器及自定义SQL详解

条件构造器 在前面学习快速入门的时候&#xff0c;练习的增删改查都是基于id去执行的&#xff0c;但是在实际开发业务中&#xff0c;增删改查的条件往往是比较复杂的&#xff0c;因此MyBatisPlus就提供了一个条件构造器来帮助构造复杂的条件。 MyBatisPlus支持各种复杂的wher…...

【前端面经】云智慧一面

写在前面&#xff1a;面经只是记录博主遇到的题目。每题的答案在编写文档的时候已经有问过deepseek&#xff0c;它只是一种比较普世的答案&#xff0c;要学得深入还是靠自己 Q&#xff1a;手撕代码&#xff0c;两个有序数组排序 A&#xff1a; function mysort(arr1, arr2) {…...