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

three.js之初识three.js

什么是three.js

Three.js是一款运行在浏览器中的 3D 引擎(基于WebGL的API的封装)

什么是WebGL?

WebGL(英语:Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。

three.js

本地环境搭建,因为spring的官方文档是访问起来比较慢,所以我们在本地搭建起来three.js的官方文档和案例

首先访问https://github.com/mrdoob/three.js 通过 git或者压缩包把代码下载到本地

使用parcel搭建three.js开发环境

为什么需要使用parcel 因为parcel不需要配置。webpack需要去进行配置。

第一个Three.js小demo

import * as THREE from "three";
//轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";//创建场景const scence=new THREE.Scene();//创建相机const camera=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000
)//设置相机位置camera.position.set(0,0,10);//添加相机到场景
scence.add(camera);//创建物体//创建几何体
const geometry=new THREE.BoxGeometry(1,1,1);
//创建材质
const meterial=new THREE.MeshBasicMaterial({color:0x00ff00});//根据几何体和材质,创建物体
const  cube=new THREE.Mesh(geometry,meterial);//控制物体移动let x=0,y=1,z=0;console.log(cube);//缩放cube.scale.set(.5,1,1.5);//旋转//   cube.rotation.set(Math.PI/2,Math.PI*2,Math.PI/3,"YXZ");
cube.rotation.set(Math.PI/4,0,0,"YZX");
//将物体添加到场景中scence.add(cube);//初始化渲染器const renderer=new THREE.WebGLRenderer();//设置渲染器的尺寸大小renderer.setSize(window.innerWidth,window.innerHeight);//将webgl渲染的fcanvas内容添加到bodydocument.body.append(renderer.domElement);
//添加坐标轴辅助器const axesHelper = new THREE.AxesHelper( 5 );
scence.add( axesHelper );//添加控制器,只有添加了控制器才能拖动查看const controller=new OrbitControls(camera,renderer.domElement);//每一帧渲染一次
const render=()=>{x+=0.01;y+=0.01;z+=0.01;if(x >5|| y >5 || z>5){x=0;y=0;z=0;}cube.position.set(x,y,z);cube.rotation.x+=0.01;//使用渲染器,通过相机将场景渲染出来renderer.render(scence,camera);// requestAnimationFrame函数是浏览器提供了,浏览器每次请求一帧则执行一次回调requestAnimationFrame(render);
}
render();

应用requestAnimationFrame

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const scence=new THREE.Scene();
const camera=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000
)
camera.position.set(0,0,10);
scence.add(camera);
const geometry=new THREE.BoxGeometry(1,1,1);
const meterial=new THREE.MeshBasicMaterial({color:0x00ff00});
const  cube=new THREE.Mesh(geometry,meterial);let x=0,y=1,z=0;console.log(cube);cube.scale.set(.5,1,1.5);
cube.rotation.set(Math.PI/4,0,0,"YZX");
scence.add(cube);
const renderer=new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.append(renderer.domElement);
const axesHelper = new THREE.AxesHelper( 5 );
scence.add( axesHelper );
const controller=new OrbitControls(camera,renderer.domElement);
const render=(time)=>{/*** time参数表示每一帧的时间* * * x+=0.01;y+=0.01;z+=0.01;* * 像这样每次加0.1是不对的,因为电脑的性能问题,会导致物体运动的不一样。* 所以我们需要让物体有规律的运行* * *///比如设置1秒运动多少const t=time/1000 %5;cube.rotation.x=t*1;x=t*1,y=t*1,z=t*1;cube.position.set(x,y,z);renderer.render(scence,camera);requestAnimationFrame(render);
}
render();

Gsap动画库(简单使用)

是一个功能十分强大的动画平台,能够帮助我们实现大部分的动画需求,构建高性能的适用于所有主流浏览器的高性能动画。

首先进行安装

  • yarn add gsap
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";//创建场景const scence=new THREE.Scene();//创建相机const camera=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000
)//设置相机位置camera.position.set(0,0,10);//添加相机到场景
scence.add(camera);//创建物体//创建集合体
const geometry=new THREE.BoxGeometry(1,1,1);
//创建材质
const meterial=new THREE.MeshBasicMaterial({color:0x00ff00});//根据几何体和材质,创建物体
const  cube=new THREE.Mesh(geometry,meterial);//控制物体移动let x=0,y=1,z=0;console.log(cube);//缩放cube.scale.set(.5,1,1.5);//旋转//   cube.rotation.set(Math.PI/2,Math.PI*2,Math.PI/3,"YXZ");
cube.rotation.set(Math.PI/4,0,0,"YZX");
//将物体添加到场景中scence.add(cube);//初始化渲染器const renderer=new THREE.WebGLRenderer();//设置渲染器的尺寸大小renderer.setSize(window.innerWidth,window.innerHeight);//将webgl渲染的fcanvas内容添加到bodydocument.body.append(renderer.domElement);
//添加坐标轴辅助器const axesHelper = new THREE.AxesHelper( 5 );
scence.add( axesHelper );//添加控制器,只有添加了控制器才能拖动查看const controller=new OrbitControls(camera,renderer.domElement);
controller.enableDamping=true
//使用gsap的动画,来帮助我们设置物体的运动
gsap.to(cube.position, {x:5, duration: 2.5, ease: "power2.in" });
//每一帧渲染一次
const render=(time)=>{//使用渲染器,通过相机将场景渲染出来renderer.render(scence,camera);// requestAnimationFrame函数是浏览器提供了,浏览器每次请求一帧则执行一次回调requestAnimationFrame(render);controller.update();
}
render();

监听画面变化,更新渲染画面

现在可以看到,当我们的浏览器的尺寸变化时,我们的渲染画面是没有跟着变的。所以我们需要监听画面的变化更新渲染页面。

//监听页面变化,更新摄像头
window.addEventListener("resize",()=>{//更新摄像头camera.aspect=window.innerWidth/window.innerHeight;//更新摄影机的摄像矩阵camera.updateProjectionMatrix();//更新渲染器renderer.setSize(window.innerWidth,window.innerHeight);//设置渲染器的像素比renderer.setPixelRatio(window.devicePixelRatio);
})
render();

js控制画面全屏与退出全屏

一般都是双击屏幕进入全屏,所以我们写双击进入&退出全屏

//给window绑定双击事件
window.addEventListener("dblclick",()=>{//获取浏览器当前的全屏对象/*** 这里因为不同浏览器的兼容,所以我们使用两个*/const fullScreenElement =document.fullScreenElement|| document.webkitFullscreenElement//当为null的时候,我们调用canvas的dom,请求进入全屏if(!fullScreenElement){renderer.domElement.requestFullscreen();}else{//直接使用document退出全屏document.exitFullscreen();}});

dat.gui

dat.gui是一个轻量级的控制器,它可以在界面上来进行操作变量。
在webgl里就是一个控制器,通过控制器来进行物体的控制。


import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
//创建场景const scence = new THREE.Scene();//创建相机const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)camera.position.set(0, 0, 10);
scence.add(camera);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const meterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, meterial);
let x = 0, y = 1, z = 0;
cube.scale.set(.5, 1, 1.5);
cube.rotation.set(Math.PI / 4, 0, 0, "YZX");scence.add(cube);const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.append(renderer.domElement);const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);const controller = new OrbitControls(camera, renderer.domElement);const gui = new datGui.GUI();//添加控制物体移动
gui.add(cube.position, 'x').min(0).max(5).step(0.01).name('移动x轴').onChange(value => {console.log("值被改变", value);}).onFinishChange(value => {{console.log("停止修改", value);}});const params = {color: '#ffff00',fn: () => { //这里的fn与下边的添加事件是对应的gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 });}
}
//颜色控制
gui.addColor(params, 'color').onChange(value => {cube.material.color.set(value);
});
//选项框
gui.add(cube, 'visible').name('是否显示');
//添加文件夹
const folder = gui.addFolder('设置立方体');
//添加文件夹内容
folder.add(cube.material, 'wireframe');
//添加点击事件
gui.add(params, 'fn').name('点击运动')
const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

认识ThreeJs物体

几何体

在three.js中所有的几何体都是基于BufferGeomatry的基础上来进行构建的。

BufferGeomatry里有三个基础属性postion(位置),normar(法向量),uv(顶点);比如说我们一个矩形的立方体,有6个面,每个面又4个顶点,就是24个顶点,然后每个顶点又x,y,z三个方向上的位置,那么这里的数据就是72个。我们可以根据顶点的位置去进行添加材质和进行贴图。我们可以通过uv来进行我们的一个材质贴图。normal的作用呢就是顶点的法向量它的作用呢就是比如有一束光进行,我们需要知道这个光的一个折射位置和面的一个朝向。

通过BufferGeomatry来创建矩形

三个顶点就可以创建一个面

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
const scence = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(0, 0, 10);
scence.add(camera);//创建基础的几何体
const geometry = new THREE.BufferGeometry();
const meterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });//设置材质//顶点位置 (由两个三角形片组成一个矩形,一个三角形片是三个顶点,两个就是六个顶点,一个顶点有三个位置所以是长度是18的一维数组)
const vertices =new Float32Array([-1.0, -1.0, 1.0,1.0, -1.0, 1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0
]);//设置顶点 (每三个数据为一个顶点)
geometry.setAttribute('position',new THREE.BufferAttribute(vertices,3));
const mesh=new THREE.Mesh(geometry,meterial);
scence.add(mesh);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);
const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);
const controller = new OrbitControls(camera, renderer.domElement);
const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

根据顶点创建酷炫三角形

//创建50个三角形,形成凌乱穿插效果
for (let i = 0; i < 50; i++) {const geometry = new THREE.BufferGeometry();//顶点坐标const positionArray = new Float32Array(9);//三个顶点组成一个三角形,每个顶点需要x,y,z三个坐标for (let j = 0; j < 9; j++) {positionArray[j] = Math.random() * 5;}geometry.setAttribute('position', new THREE.BufferAttribute(positionArray, 3));//颜色进行随机const color = new THREE.Color(Math.random(), Math.random(), Math.random());//创建材质const meterial = new THREE.MeshBasicMaterial({color,transparent: true,//保持透明,opacity: .5 //透明度});const mesh = new THREE.Mesh(geometry, meterial);scence.add(mesh);
}

常用的网格几何体

three.js中给我们提供了很多的几何体我们可以去进行使用,不用自己再去进行设置一个很多顶点。

我们都可以通过在文档中去查找几何体,然后通过设置他们的构造参数来得到想要的物体。

认识Three的材质

上一个我们说到了物体,也就是几何体,我们通过几何体与材质进行一个贴合,才构建成了我们的一个物体。

基本颜色材质搭建

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
const scence = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(0, 0, 10);
scence.add(camera);
const renderer = new THREE.WebGLRenderer();
// 创建一个正方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//导入纹理
const textureLoader=new THREE.TextureLoader().load('./public/door.jpg');
//创建材质
/*** map是颜色材质纹理,具体的我们可以看文档*/
const material = new THREE.MeshBasicMaterial({ map:textureLoader});
const cube = new THREE.Mesh(geometry, material);
scence.add(cube);
renderer.setSize(window.innerWidth, window.innerHeight);document.body.append(renderer.domElement);const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);const controller = new OrbitControls(camera, renderer.domElement);const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

纹理偏移 旋转 重复

three.js给我们提供了,纹理在物体上如何进行设置(旋转,偏移,重复)

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
const scence = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(0, 0, 10);
scence.add(camera);
const renderer = new THREE.WebGLRenderer();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const texture = new THREE.TextureLoader().load('./public/door.jpg');
//纹理偏移
// texture.offset.set(0.5,0.5);//纹理旋转
//texture.rotation=Math.PI/4;
//texture.center.set(0.5,0.5); //设置旋转原点//纹理重复texture.repeat.set(2, 3);
texture.wrapS=THREE.MirroredRepeatWrapping;
texture.wrapT=THREE.RepeatWrapping;
/*** wrapS 指代的是水平方向上纹理重复如何包裹* wrapT 指代的是垂直方向上纹理重复如何包裹* MirroredRepeatWrapping和RepeatWrapping是three.js提供的常量值*/
const material = new THREE.MeshBasicMaterial({ map: texture });
const cube = new THREE.Mesh(geometry, material);
scence.add(cube);
renderer.setSize(window.innerWidth, window.innerHeight);document.body.append(renderer.domElement);const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);const controller = new OrbitControls(camera, renderer.domElement);const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

纹理的显示算法

magFilter,就是在渲染时一个纹素覆盖多个屏幕项目的情况下如何对这些纹素采样确定最终的颜色,
当使用THREE.LinerFilter时,它表示贴图将使用四个最接近的纹素,并在它们之间进行双线性插值。
当设置为THREE.NearestFilter时,它表示贴图将使用最接近的单个纹素的值,这意味着只会考虑最接近的一个纹素,而不考虑周围其他的纹素。

minFilter 当一个纹素小于一个屏幕像素时的设置

透明纹理

透明纹理的含义的就是,比如我们的门的图片,它展示的不仅仅是一个门的形状,它还包括边缘的一些形状,那么怎么办呢?three.js的材质里提供了属性alphaMap,它可以通过导入进来的材质图片,导入的材质图片吧必须只有黑色和白色,黑色就是完全透明,白色就是完全不透明,贴入之后,来展示形状,比如我们第二个导入进来的黑白图片,白色的就只是一个门的形状,在贴入之后我们就只能看到门了。

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
const scence = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(0, 0, 10);
scence.add(camera);
const renderer = new THREE.WebGLRenderer();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const texture = new THREE.TextureLoader().load('./public/door.jpg');
//导入透明材质纹理图片
const alphaMap=new THREE.TextureLoader().load('./public/door_opticy.jpeg');
const material = new THREE.MeshBasicMaterial({ map: texture,alphaMap, // 透明材质transparent:true, //透明side:THREE.DoubleSide  //单面 || 双面显示});
const cube = new THREE.Mesh(geometry, material);
scence.add(cube);
renderer.setSize(window.innerWidth, window.innerHeight);document.body.append(renderer.domElement);const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);const controller = new OrbitControls(camera, renderer.domElement);const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

环境遮挡贴图

环境贴图,就是比如我们的门,门上的一些纹理,我们需要显示的更加真实。

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as datGui from 'dat.gui';
const scence = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(0, 0, 10);
scence.add(camera);
const renderer = new THREE.WebGLRenderer();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const texture = new THREE.TextureLoader().load('./public/door.jpg');
const alphaMap=new THREE.TextureLoader().load('./public/door_opticy.jpeg');
//引入环境贴图的图片
const aoMap=new THREE.TextureLoader().load('./public/aoDoor.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture,alphaMap,transparent:true,aoMap,side:THREE.DoubleSide });//规定,使用aoMap环境贴图的话需要给几何体添加第二组uv
geometry.setAttribute('uv2',new THREE.BufferAttribute(geometry.attributes.uv.array,2));
const cube = new THREE.Mesh(geometry, material);scence.add(cube);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);const controller = new OrbitControls(camera, renderer.domElement);const render = () => {renderer.render(scence, camera);requestAnimationFrame(render);
}
render();

相关文章:

three.js之初识three.js

什么是three.js Three.js是一款运行在浏览器中的 3D 引擎&#xff08;基于WebGL的API的封装&#xff09; 什么是WebGL&#xff1f; WebGL&#xff08;英语&#xff1a;Web Graphics Library&#xff09;是一种3D绘图协议&#xff0c;这种绘图技术标准允许把JavaScript和Open…...

二维码智慧门牌管理系统:地址管理的现代革命

文章目录 前言一、标准地址的革新二、广泛的应用前景 前言 在科技不断发展和社会进步的背景下&#xff0c;高效、精准、智能的管理系统已经成为当今社会的迫切需求。传统的门牌管理系统在应对这一需求方面已显得力不从心&#xff0c;因此&#xff0c;二维码智慧门牌管理系统的…...

BricsCAD 23 for Mac:轻松驾驭CAD建模的强大工具

如果你正在寻找一款功能强大、操作简便的CAD建模软件&#xff0c;那么BricsCAD 23 for Mac绝对值得你考虑。这款软件将为你提供一套完整的2D和3D设计解决方案&#xff0c;让你在Mac上轻松创建、编辑和修改图形。 一、BricsCAD 23的功能特点 高效的2D和3D建模&#xff1a;Bric…...

如何利用Web应用防火墙应对未知威胁

网络安全是一个永恒的话题&#xff0c;尤其是在未知威胁不断涌现的情况下。Web应用防火墙&#xff08;WAF&#xff09;是企业网络安全防线的重要组成部分&#xff0c;能够帮助企业在面对未知威胁时采取有效的防护措施。本文将探讨如何利用Web应用防火墙应对未知的网络威胁。 一…...

四、多线程服务器

1.进程的缺陷和线程的优点 1.进程的缺陷 创建进程&#xff08;复制&#xff09;的工作本身会给操作系统带来相当沉重的负担。 而且&#xff0c;每个进程具有独立的内存空间&#xff0c;所以进程间通信的实现难度也会随之提高。 同时&#xff0c;上下文切换&#xff08;Cont…...

基于vue实现滑块动画效果

主要实现&#xff1a;通过鼠标移移动、触摸元素、鼠标释放、离开元素事件来进行触发 创建了一个滑动盒子&#xff0c;其中包含一个滑块图片。通过鼠标按下或触摸开始事件&#xff0c;开始跟踪滑块的位置和鼠标/触摸位置之间的偏移量。然后&#xff0c;通过计算偏移量和起始时的…...

探寻蓝牙的未来:从蓝牙1.0到蓝牙5.4,如何引领无线连接革命?

►►►蓝牙名字的来源 这要源于一个小故事&#xff0c;公元940-985年&#xff0c;哈洛德布美塔特(Harald Blatand)&#xff0c;后人称Harald Bluetooth&#xff0c;统一了整个丹麦。他的名字“Blatand”可能取自两个古老的丹麦词语。“bla”意思是黑皮肤的&#xff0c;而“tan…...

openssl 之 RSA加密数据设置OAEP SHA256填充方式

背景 如题 环境 openssl 1.1.1l c centos7.9 代码 /** 思路&#xff1a;填充方式自己写&#xff0c;不需要使用库提供的&#xff0c;然后加密时选择不填充的方式加密 关键代码 */ int padding_result RSA_padding_add_PKCS1_OAEP_mgf1(buf, padding_len, (unsigned char*…...

js将带标签的内容转为纯文本

背景&#xff1a;现需要将富文本的所有 html 标签全部删除得到纯文本 思路&#xff1a;创建临时DOM元素并获取其中的文本 创建一个临时 DOM 并给他赋值&#xff0c;然后我们使用 DOM 对象方法提取文本。 代码如下&#xff1a; convertToPlain( html){//新创建一个 divvar di…...

如何通过内网穿透实现远程连接NAS群晖drive并挂载电脑硬盘?

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…...

4.2 抽象类

1. 抽象类概念 定义一个类时&#xff0c;常常需要定义一些成员方法用于描述类的行为特征&#xff0c;但有时这些方法的实现方式是无法确定的。例如&#xff0c;Animal类中的shout()方法用于描述动物的叫声&#xff0c;但是不同的动物&#xff0c;叫声也不相同&#xff0c;因此…...

ITextRenderer将PDF转换为HTML详细教程

引入依赖 <dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf-itext5</artifactId><version>9.1.18</version></dependency> 问题一&#xff1a;输出中文字体 下载字体simsun.ttc 下载链接&am…...

c#设计模式-行为型模式 之 备忘录模式

&#x1f680;简介 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;它保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对象。所谓备忘录模式就是在不破坏封装的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象…...

ffmpeg+安卓+yolo+RK3399部署

一次满足多项需求. 首先, 思路是, 使用ffmpeg解码本地mp4文件, 在无需任何其他改动的情况下, 就可以直接播放rtsp流, 这个是使用ffmpeg的好处. ffmpeg本身是c语言的, 所以需要编译成jni的库, https://note.youdao.com/s/6XeYftc 具体过程在这里, 用windows/macOS, Ubuntu应该都…...

发电机教程:小白必学的柴油发电机技巧

柴油发电机监控是关键的能源管理和维护工具&#xff0c;它用于确保持续的电力供应&#xff0c;提高能源效率&#xff0c;并延长发电机的寿命。 随着科技的不断发展&#xff0c;监控系统变得更加智能和高效&#xff0c;使用户能够远程监测和管理柴油发电机的运行状态。 客户案例…...

基础课1——人工智能的分类和层次

1.人工智能的分类 人工智能&#xff08;AI&#xff09;的分类主要有以下几种&#xff1a; 弱人工智能&#xff08;Artificial Narrow Intelligence&#xff0c;ANI&#xff09;&#xff1a;弱人工智能是擅长于单个方面的人工智能&#xff0c;例如战胜象棋世界冠军的人工智能阿…...

C语言复杂表达式与指针高级

一、指针数组与数组指针 1.指针数组VS数组指针 &#xff08;1&#xff09;指针数组&#xff1a;实质是一个数组&#xff0c;因为这个数组中传参的内容全部是指针变量。 &#xff08;2&#xff09;数组指针&#xff1a;实质是一个指针&#xff0c;这个指针指向一个数组 2.分析指…...

【Python从入门到进阶】39、使用Selenium自动验证滑块登录

接上篇《38、selenium关于Chrome handless的基本使用》 上一篇我们介绍了selenium中有关Chrome的无头版浏览器Chrome Handless的使用。本篇我们使用selenium做一些常见的复杂验证功能&#xff0c;首先我们来讲解如何进行滑块自动验证的操作。 一、测试用例介绍 我们要通过sel…...

利用FPGA和CPLD数字逻辑实现模数转换器

数字系统的嵌入式工程师熟悉如何通过使用FPGA和CPLD在其印刷电路板上将各种处理器&#xff0c;存储器和标准功能组件粘合在一起来实现其数字设计的“剩余”。除了这些数字功能之外&#xff0c;FPGA和CPLD还可以使用LVDS输入&#xff0c;简单的电阻电容器&#xff08;RC&#xf…...

上海亚商投顾:沪指震荡调整跌 减肥药、华为概念股持续活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 沪指上个交易日低开后震荡调整&#xff0c;深成指、创业板指盘中跌超1%&#xff0c;宁德时代一度跌超3%&#xff…...

移步皆海景处处可停留,读懂大连海岸的松弛质感

沿着大连的滨海路漫步&#xff0c;你会遇见这座城市最从容的一面。这条贯穿海滨风景线的道路&#xff0c;串联起星海广场、森林动物园、老虎滩海洋公园等多个开放型景观区域&#xff0c;核心特点在于它并不急于展示某个单一景点&#xff0c;而是将城市生活与自然海岸融为一体—…...

基于CircuitPython与BLE的NeoPixel智能穿戴灯光项目实战

1. 项目概述&#xff1a;打造你的第一顶可编程发光帽 几年前&#xff0c;当我第一次在Maker Faire上看到有人戴着一顶能随着音乐节奏变换色彩的帽子时&#xff0c;我就被深深吸引了。那不仅仅是一个电子项目&#xff0c;更像是一件充满个性的可穿戴艺术品。从那时起&#xff0…...

基于RAG与向量数据库的智能代码搜索工具设计与实现

1. 项目概述&#xff1a;一个面向开发者的智能代码搜索与理解工具 最近在GitHub上看到一个挺有意思的项目&#xff0c;叫 holasoymalva/perplexity-code 。乍一看这个标题&#xff0c;可能会有点困惑——“perplexity”在机器学习里通常指“困惑度”&#xff0c;是衡量语言模…...

换背景颜色怎么操作?5分钟掌握证件照、商品图换底色的完整指南

最近有不少朋友问我&#xff0c;证件照背景太丑怎么办&#xff1f;电商产品图背景杂乱怎么处理&#xff1f;其实换背景颜色没有想象中那么复杂&#xff0c;今天就把我用过的所有方法和工具整理出来&#xff0c;帮你彻底解决这个问题。为什么要学会换背景颜色先说说我为什么突然…...

Next.js企业级项目脚手架:架构设计、工程化实践与生产部署指南

1. 项目概述&#xff1a;一个为Next.js量身打造的企业级起点如果你正在寻找一个能让你快速启动Next.js项目&#xff0c;同时又不想在项目初期就陷入繁琐的脚手架搭建、代码规范配置和基础架构设计的泥潭&#xff0c;那么once-ui-system/nextjs-starter这个项目很可能就是你一直…...

为什么92%的AIGC剪辑师仍在用手动导出?揭秘Sora 2直连Premiere的7大底层优化与3个避坑红线

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Sora 2与Premiere直连整合的行业悖论与破局起点 当OpenAI正式释放Sora 2的API文档并开放有限开发者预览时&#xff0c;Adobe Premiere Pro团队内部立即启动了“Project Lumen”——一项旨在实现双向帧级…...

如何提升SQL存储过程逻辑复用_封装通用存储过程函数

SQL Server无函数式存储过程&#xff0c;需用标量函数&#xff08;单值计算&#xff09;或表值函数&#xff08;结果集&#xff09;替代&#xff1b;标量函数禁用DML和非确定性函数&#xff0c;ITVF性能优于MSTVF&#xff1b;MySQL函数须声明DETERMINISTIC等属性&#xff1b;跨…...

Taotoken API Key的精细化管理与审计日志功能实践

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken API Key的精细化管理与审计日志功能实践 对于需要将大模型能力集成到业务流程中的团队而言&#xff0c;API Key的管理与安…...

数字电路小白也能懂:用Logisim搞定LED计数电路,从真值表到封装测试保姆级教程

数字电路零基础实战&#xff1a;用Logisim构建LED计数器的完整指南 从困惑到清晰&#xff1a;为什么选择Logisim作为数字电路入门工具 第一次接触数字电路时&#xff0c;面对密密麻麻的逻辑门和抽象的真值表&#xff0c;大多数初学者都会感到无从下手。传统教材中复杂的公式推导…...

ubuntu linux虚拟机安装部署hermes详细教程(安装、问题处理)

文章目录 前言 一、Hermes 介绍 1. 什么是 Hermes Agent? 2. 核心特性 3. 为什么选择 Hermes Agent? 4. 适用场景 二、安装Hermes 1.安装 2.配置 3.开始对话 4.接入多平台(可选) 5.保持更新 三、Hermes接入微信 四、常见错误解决 1.Failed to connect to github.com port 4…...