three.js 基础认识与简单应用

news2025/5/26 7:52:00

一、前言

1. 什么是three.js?你将它理解成three+js,three表示3D的意思,js表示JavaScript的意思,合起来,three.js就是使用JavaScript来写3D程序的意思。three.js是基于WebGL的一个运行在浏览器上的开源框架,使得WebGL的使用更方便、快捷,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。
2. three.js是基于webGL封装的库,保留了webGL的灵活性,开源免费,可以满足大部分的3D需求。

二、学习参考资料

官网:Three.js – JavaScript 3D Library

官网中文文档(通过 方式本地搭建three.js官网): three.js docs

 学习推荐:

郭隆邦_技术博客:WebGL

webGL中文网:WebGL中文网

三、本地搭建three.js官网

 第一步:进入官网  Three.js – JavaScript 3D Library

 第二步:点击code中的github

 第三步:dev分支---- code中Download ZIP

 第四步:vscode编辑器打开---- npm install  下载依赖包、打开package.json查看运行方式(这里是 npm start 如图)

 第五步:打开上方运行出的https地址可以查看到:

three.js-dev目录结构示意图: 

 第六步:点击 three.js-dev目录 中的 docs 文件夹

四、three.js安装引入

 以下的例子都是按照npm的方式安装的 

五、基础知识

1、右手坐标系
        three.js中使用的都是右手坐标系,即图示右手大拇指指向x轴正向,食指指向y轴正向,中指指向z轴正向,这样的一个三维坐标系。具体来说,x,y坐标用于控制浏览器平面,如果不改变z坐标则物体只在浏览器平面上运动,因此z坐标控制的就是远近

 

 2、整个程序解构:

  程序整个运行过程就是:场景 —— 相机 —— 渲染器

六、three.js核心组成 

1、场景(secne)  

/*
 *1. 创建场景  -- 放置物体对象的环境
 */
const scene = new THREE.Scene();

2、相机(camera)

(1)、创建透视相机,也称投影相机(PerspectiveCamera)-- 用来模拟人眼所看到的景象

/*
 * 2.创建相机(这里是 透视摄像机--用来模拟人眼所看到的景象)
 */
const camera = new THREE.PerspectiveCamera(
  75, // 视野角度
  window.innerWidth / window.innerHeight, // 长宽比
  0.1, // 进截面
  1000 // 远截面
);
// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera); // 将相机添加到场景中

分析: 

const camera = new THREE.PerspectiveCamera(

        fov : Number,

        aspect : Number,

        near : Number,

        far : Number

)


fov — 摄像机视锥体垂直视野角度 (相机的拍摄视角大小)
aspect — 摄像机视锥体长宽比 (相机拍摄区域的长宽比)
near — 摄像机视锥体近端面 (相机拍摄范围近端距离)
far — 摄像机视锥体远端面 (相机拍摄范围远端距离)
常用:const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );


效果:相机拍摄的画面具有近大远小的特性,距离相机的物体显示的,距离相机的物体显示的

ps: 在 Three 中是没有「长度单位」这个概念的,它的数值都是根据比例计算得出,因此这里提到的 0.1 或 1000 都没有具体的含义,而是一种相对长度。 

 

可以看到,通过配置透视相机的相关参数,最终被渲染到屏幕上的,是在 near 到 far 之间,根据 fov 的值物体远近确定渲染高度,再通过 aspect 值来确定渲染宽度的。

或者更直观一点显示:

如图中所示,透视投影相机一共有4个参数:fov(视场,一个角度值), Horizonta Field of View(横向视场),Vertical Field of View(纵向视场),Near plane(近面), Far plane(远面);由这几个因素,构成一个六面体的封闭空间,在这个空间内的一切物体可见。在设置参数时,需满足:

横向视场 / 纵向视场 = 浏览器窗口的宽/浏览器窗口的高。

(2)、创建正交相机

const camera = new THREE.OrthographicCamera(

        left : Number,

        right : Number,

        top : Number,

        bottom : Number,

        near : Number,

        far : Number

)
left — 摄像机视锥体左侧面。
right — 摄像机视锥体右侧面。
top — 摄像机视锥体上侧面。
bottom — 摄像机视锥体下侧面。
near — 摄像机视锥体近端面 (表示近平面与相机中心点的垂直距离)。
far — 摄像机视锥体远端面 (表示远平面与相机中心点的垂直距离)。

效果:相机拍摄的画面是相机对物体的正投影,无论物体远近都不会影响它在相机画面中的大小。


各参数如图所示:

 

 分析与ps:

1、由图可知正交透视相机总共有6个面,其具备的特点是:场景中远处的物体和近处的物体是一样大的,它并不像我们现实生活中看场景那样,远小近大,而是远近皆一样大;6个面分别为left(左面),right(右面),top(顶面),bottom(底面),near(近面),near(远面),这六个面组成一个封闭的矩形空间,在这个空间内的一切物体都可见。在设置其参数的时候,下面的关系式一定要成立:

left right = 1,top / buttom | = 1

2、由图可见near与far的值应为正值,且far>near。如果最后两个值是(0,0),也就是near和far值相同了,视景体深度没有了,整个视景体都被压成个平面了,就会显示不正确。

将摄像机聚焦在指定点

注意: 默认相机的位置在(0,0,0)点处,即场景中心,如果物体也在该点则拍摄不到,所以我们要适当调整相机的位置

使用camera.position.set(x, y, z)来设置摄像机的位置。

使用camera.lookAt(new THREE.Vector3(x, y, z))来改变摄像机的指向位置。        

        例如,指向场景中心:camera.lookAt(scene.position)

总结:

透视相机(PerspectiveCamera):近大远小
正交相机(OrthographicCamera):远近一致 

 

 3、渲染器(render)

        有了场景相机,我们还需要渲染器把对应的场景用对应的相机可见渲染出来,因此渲染器需要传入场景和相机参数。 

/*
 *  3.初始化渲染器-设置渲染器大小及挂载元素
 */
const renderer = new THREE.WebGL1Renderer();

// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);

// 清除颜色,第二个参数为 0 表示完全透明,适用于需要透出背景的场景
// renderer.setClearColor(0x000000, 0);

// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// 使用渲染器,通过相机将场景渲染出来
renderer.render(scene, camera);

const renderer = new THREE.WebGLRenderer();
document.body.appendChild( renderer.domElement );
实例化一个渲染器,然后将它的dom元素插入到body中,即插入了一个canvas。


也可以将其插入到其他元素中,比如html中有一个<div id='canvas'></div>,就可以写成
document.getElementById('canvas').appendChild( renderer.domElement );这样场景就在这个div中加载了。


注意:设置渲染器的大小,常用的为renderer.setSize( window.innerWidth, window.innerHeight );,如果不设就是默认大小

现在 场景、相机、渲染器都有了,就差需要展示的对象了,下面就来介绍一下物体(几何体)对象

4、物体对象  -- 包含 几何体(Geometry)、材质(Material)、网格对象(Mesh)

/*
 *  添加物体
 */
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); // 创建几何体对象 -- 立方体
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建材质
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); //创建网格,网格=对象+材质
scene.add(cube); // 将物体添加到场景中

几何体(Geometry)

         Three 提供了多种类型的几何体,可以分为二维网格和三维网格。二维网格顾名思义只有两个维度,可以通过这种几何体创建简单的二维平面;三维网格允许你定义三维物体;在 Three 中定义一个几何体十分简单,只需要选择需要的几何体并传入相应参数创建即可。常用几何体如下:

        更多几何体及相关用法请见官网: 官网:Three.js – JavaScript 3D Library

        三维:

构造函数说明
THREE.BoxGeometry立方几何体
THREE.SphereGeometry球几何体
HREE.ConeGeometry圆锥几何体
HREE.CylinderGeometry圆柱几何体
HREE.TorusGeometry圆环几何体
HREE.TextGeometry文本几何体

        二维:

材质(Material)

        定义材质可以帮助我们决定一个物体在各种环境情况下的具体表现。同样 Three 也提供了多种材质。下面列举几个常用的材质。

        更多材质及相关用法请见官网: 官网:Three.js – JavaScript 3D Library

        创建材质:

const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x666666 });
const lambertMaterial = new THREE.MeshLambertMaterial({ color: 0x666666 });
const phongMaterial = new THREE.MeshPhongMaterial({ color: 0x666666 });
const wireMaterial = new THREE.MeshBasicMaterial({ wireframe: true, color: 0x666666 });

网格对象(Mesh)

         需要将几何体和材质添加到场景中,还需要依赖 Mesh。Mesh 是用来定义材质和几何体之间是如何粘合的。

或者说 3d物体由点->线->面组成,mesh网格就是由大量的面组成的网格图,再加上材质就创建成物体,新建几何体和材质后,就可以将该物体对象添加到场景中了。

创建网格对象可以应用一个或多个材质和几何体。

网格 = 几何体 + 材质

创建几何体相同材质不同的网格对象:

const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
const cubePhong = new THREE.Mesh(cubeGeometry, phongMaterial);
scene.add(cube, cubePhong);

创建材质相同几何体不同的网格对象:

const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
const sphere = new THREE.Mesh(sphereGeometry, basicMaterial);
scene.add(cube, sphere);

 创建拥有多个材质几何体的网格对象:

const phongMaterial = new THREE.MeshPhongMaterial({ color: 0x666666 });
const cubeMeshPhong = new THREE.Mesh(cubeGeometry, cubePhongMaterial);
const cubeMeshWire = new THREE.Mesh(cubeGeometry, wireMaterial);
// 网格对象新增材质
cubeMeshPhong.add(cubeMeshWire);
scene.add(cubeMeshPhong);

有了场景、相机和渲染器,再加上物体,我们已经可以看到初步的效果了。但3D世界里,静止的物体多无趣啊。于是我们尝试加入动画效果.。

5、帧循环,游戏循环: 

// 定义循环渲染方法
function render() {
  // 物体动态移动位置 -- 沿x轴
  cube.position.x += 0.01;
  if (cube.position.x > 7) {
    cube.position.x = 0;
  }
  // 物体动态旋转
  cube.rotateX(0.01); //每次绕y轴旋转0.01弧度
  // cube.rotation.x += 0.01;

  renderer.render(scene, camera); // 执行渲染操作
  requestAnimationFrame(render); // 渲染下一帧的时候就会调用render函数
}
render();

6、灯光

1、灯光用来为场景添加光源,照明物体,虽然部分材质(如MeshBasicMaterial)不会受到灯光的影响,无需添加灯光也能看见,但是这种材质的物体没有质感,也没有明暗变化;如果想让物体更接近真实场景的物体,就需要可以被灯光影响的材质,如MeshLamberMaterial,如果不添加光源就无法看到物体。


2、灯光分为点光源线光源面光源等,可依据实际场景进行选择,正如真实场景的光源情况,three.js允许添加多个灯光从而对真实场景进行模拟。


添加灯光方法:
const light = new THREE.AmbientLight( 0x404040 ); 
scene.add( light );

 

7、辅助线

// 三维辅助线(长度)-- 三维坐标系
const axisHelper = new THREE.AxisHelper(7);
scene.add(axisHelper);
 
// 网格辅助线 -- 地表格(网格宽度、等分数、中心线颜色,网格线颜色)
const grid = new THREE.GridHelper(1000, 1000, 0xff0000, 0xff0000);
scene.add(grid);

8、轨道控制器查看物体(鼠标控制)

// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

/**
 * 创建轨道控制器(OrbitControls)
 * 可以使得相机围绕目标进行轨道运动
 */
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true; // 相机是否自动旋转
controls.autoRotateSpeed = 3; // 自转速度

 PS:这个属性为true时 在动画循环方法中应添加 controls.update();  例如:

// 定义循环渲染方法
function render() {
  // 动态移动位置
  cube.position.x += 0.01;
  if (cube.position.x > 7) {
    cube.position.x = 0;
  }
  //动态旋转
  cube.rotateX(0.01); //每次绕y轴旋转0.01弧度
  // cube.rotation.x += 0.01;

  renderer.render(scene, camera); // 执行渲染操作

  controls.update(); // controls控制特定属性时加

  requestAnimationFrame(render); // 渲染下一帧的时候就会调用render函数
}
render();

能把上面的看完,基本上自己就可以实现3d效果了, 那下面就简单给出几个例子帮助理解一下!

示例一:通过script标签来引入three.js比较简单,适合简单的练习,快速体验。

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>My First three.js app</title>
        <script src="js/three.min.js"></script>
  <style>
   body{margin:0;}
  </style>
 </head>
 <body>
 <script>
  // 场景
  const scene = new THREE.Scene();
 
  // 相机
  const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,000);
 
  // 渲染器
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth,window.innerHeight);
  document.body.appendChild(renderer.domElement);
 
  // 物体
  const geometry = new THREE.BoxGeometry(1,1,1);
  const material = new THREE.MeshBasicMaterial({color:0x00ff00});
  const cube = new THREE.Mesh(geometry,material);
  scene.add(cube);
 
  camera.position.z = 5;

  // 动画
  const animate = function(){
   requestAnimationFrame(animate);
   cube.rotation.x += 0.01;
   cube.rotation.y += 0.01;
   renderer.render(scene,camera);  //渲染
  };
  animate();
 </script>
 </body>
</html>

 这是一张静态图片,动态效果自己运行一下就能出现啦!  

 

示例二:通过script标签和CDN来引入three.min.js,实现一个旋转的球:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>My First three.js app2</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <script src='https://cdn.bootcss.com/three.js/91/three.min.js'></script>
</head>

<body>
    <script>
        //创建场景
        const scene = new THREE.Scene();
        //创建透视投影相机,视角45度,画幅比例 宽比高,近平面距离0.1,远平面1000
        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
        //创建渲染器
        const renderer = new THREE.WebGLRenderer();
        //渲染器canvas宽高设为与窗口一致
        renderer.setSize(window.innerWidth, window.innerHeight);
        //将渲染器对应的dom元素添加到body中
        document.body.appendChild(renderer.domElement);
        //定义一个几何体
        const geometry = new THREE.SphereGeometry(3, 30, 30);
        //定义一种材质,显示为线框
        const material = new THREE.MeshBasicMaterial({ color: 0xB3DD, wireframe: true });
        //网孔(Mesh)是用来承载几何模型的一个对象,可以把材料应用到它上面
        const ball = new THREE.Mesh(geometry, material);
        //把几何模型添加到场景中,对象被添加到原点(0,0,0)坐标。
        scene.add(ball);
        //移动相机位置
        camera.position.z = 8;
        function render() {
            //渲染循环,以每秒60次的频率来绘制场景
            requestAnimationFrame(render);
            //设置球体绕y轴旋转
            ball.rotation.y += 0.005;
            renderer.render(scene, camera);
        }
        render();
    </script>
</body>

</html>

 这是一张静态图片,动态效果自己运行一下就能出现啦! 

示例三、通过npman安装,在vue2项目中使用:

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

/*
*1. 创建场景
*/
const scene = new THREE.Scene();

/*
* 2.创建相机(这里是 透视摄像机--用来模拟人眼所看到的景象)
*/
const camera = new THREE.PerspectiveCamera(
75, // 视野角度
window.innerWidth / window.innerHeight, // 长宽比
0.1, // 进截面
1000 // 远截面
);
// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera); // 将相机添加到场景中

/*
* 添加物体
*/
// 创建几何体对象
const cubeGeometry = new THREE.BoxGeometry(1.5, 1.5, 1.5);
// 设置材质
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 网格 = 对象 + 材质
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube); // 将物体添加到场景中

// 修改物体的位置(想实现动态的移动就定义在render()方法中)
// cube.position.set(7, 0, 0);
// 或者
// cube.position.x = 7;

// 缩放
// cube.scale.set(3, 2, 1);
// 或者
// cube.scale.x = 3;

// 旋转(参数有4个,前面是xyz,第四个可以控制旋转的顺序)--想实现动态的旋转就定义在render()方法中
// cube.rotation.set(Math.PI / 4, 0, 0, "XZY");
// 或者
// cube.rotateX(Math.PI / 4);
// 或者
cube.rotation.x = Math.PI / 4;

/**
* 3.初始化渲染器
*/
const renderer = new THREE.WebGL1Renderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// 使用渲染器,通过相机将场景渲染出来
// renderer.render(scene, camera);

/**
* 创建轨道控制器(OrbitControls)
* 可以使得相机围绕目标进行轨道运动
*/
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true; // 相机是否自动旋转
controls.autoRotateSpeed = 3; // 自转速度

/**
* 辅助三维坐标系
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
var axesHelper = new THREE.AxesHelper(7);
scene.add(axesHelper);

// 定义循环渲染方法
function render() {
// 动态移动位置
cube.position.x += 0.01;
if (cube.position.x > 7) {
cube.position.x = 0;
}
//动态旋转
cube.rotateX(0.01); //每次绕y轴旋转0.01弧度
// cube.rotation.x += 0.01;

renderer.render(scene, camera); // 执行渲染操作
controls.update(); // controls控制特定属性时加
requestAnimationFrame(render); // 渲染下一帧的时候就会调用render函数
}
render();

 这是一张静态图片,动态效果自己运行一下就能出现啦! 

Thanks !!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业级安全软件装机量可能大增

声明 本文是学习大中型政企机构网络安全建设发展趋势研究报告. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 研究背景 大中型政企机构是网络安全保护的重中之重&#xff0c;也是国内网络安全建设投入最大&#xff0c;应用新技术、新产品最多的机构…

云原生系列之使用 prometheus监控MySQL实战

文章目录前言一. 实验环境二. 安装MySQL5.72.1 配置yum源2.2 安装MySQL之前的环境检查2.3 开始使用yum安装2.4 启动MySQL并测试三. 安装MySQL_exporter3.1 MySQL_exporter的介绍3.2 mysql_exporter的安装3.3 设置MySQL账户&#xff0c;用于数据收集3.4 启动mysql_exporter3.5 配…

2023年信息系统项目管理师,需要哪些备考资料?

其实考前心态是相当重要的&#xff0c;你需要战胜的一直是你自己。你首先要明确自己考试必胜的决心&#xff0c;树立好的备考心态&#xff0c;学习只要用对了方法&#xff0c;考试通过的几率还是挺高的。备考心得&#xff1a;我自己备考了3个月的时间通过了&#xff0c;分享一套…

Linux多线程---生产者消费者模型和线程池

目录 生产者消费者模型 条件变量 接口 实现基于阻塞队列的cp模型 POSIX信号量 信号量的PV操作 接口&#xff1a; 初始化信号量&#xff1a; 销毁信号量 等待信号量 发布信号量 基于环形队列的生产者消费者模型 线程池 应用场景&#xff1a; 如何实现&#xff1f; …

DHCP中继及配置

为什么需要DHCP Relay&#xff1f;产生背景解决方案DHCP Relay工作原理DHCP Relay配置实现产生背景 随着网络规模的扩大&#xff0c;网络中就会出现用户处于不同网段的情况。 这个时候客户A和客户B要请求IP地址时&#xff0c;首先会发送DHCP Discover广播包&#xff0c;这个广…

一本关于ChatGPT的书《ChatGPT 革命:了解大型语言模型的力量》免费下载

下载地址&#xff1a;https://download.csdn.net/download/winniezhang/87431530 这本书有什么不同&#xff1a; 1、从书名&#xff0c;到大纲&#xff0c;到内容&#xff0c;基本都来自ChatGPT的自述&#xff0c;本人只是负责编辑。 2、整个成书过程只用了2小时不到。 3、…

【排序算法】堆排序(Heap Sort)

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构&#xff0c;并同时满足堆积的性质&#xff1a;即子结点的键值或索引总是小于&#xff08;或者大于&#xff09;它的父节点。堆排序介绍学习堆排序之前&#xff0c;有必要了解堆&#xff01;若…

【HTML】HTML 表格 ② ( 表头单元格标签 | 表格标题标签 )

文章目录一、表头单元格标签二、表格标题标签一、表头单元格标签 表头单元格 可以在表格中 用作第一排 作为表格 的 表头 使用 , 表头单元格 中的 文本设置 可以与 普通单元格 中的文本设置 不同 ; 表头单元格 中的 文本 会 居中 , 并且 加粗 显示 ; 表头单元格 标签 如下 : &…

2023彻底解决Typora使用iPic微博图床失效问题

一、问题描述用Typora搭配iPic图床使用&#xff0c;最近csdn图片显示不出来用浏览器打开图片显示403&#xff0c;这里原因是微博图床出问题了导致的而使用iPic其他图床则需要一直付费&#xff0c;那有没有一劳永逸的解决所有问题呢&#xff1f;二、旧图恢复首先怎么找回旧图&am…

数字信号处理-第一章 离散时间信号与系统

1.1 离散时间信号——序列 1.1.1 序列 离散时间信号只在离散时间上给出函数值&#xff0c;是时间上不连续的序列。一 般 &#xff0c;离散时间的间隔是均匀的&#xff0c;以TTT表示&#xff0c;故用 x(nT)x(nT)x(nT)表示此离散时间信号在nTnTnT点上的值&#xff0c;nnn为整数…

省钱的年轻人,钱包被折扣店钻了空子

【潮汐商业评论/原创】过年期间&#xff0c;除了商场超市&#xff0c;小区附近的折扣店成了Amy经常光顾的对象。用Amy的话来说&#xff0c;“跟附近超市比价格&#xff0c;跟大卖场比距离&#xff0c;综合下来折扣店就是我随时购物的不二选择。”从Amy的话里&#xff0c;我们可…

LeetCode-101. 对称二叉树

目录题目分析递归法题目来源 101. 对称二叉树 题目分析 首先想清楚&#xff0c;判断对称二叉树要比较的是哪两个节点&#xff0c;要比较的可不是左右节点&#xff01; 对于二叉树是否对称&#xff0c;要比较的是根节点的左子树与右子树是不是相互翻转的&#xff0c;理解这一…

如何在 Mac 上将 PDF 转换为 Word [6 种免费方法]

我们出于各种原因使用 PDF。我们可以将它们用于学校作业&#xff0c;以打印出谱&#xff0c;或离线阅读文章。我们经常想弄清楚如何在 Mac 上将 Word 文档另存为 PDF。但是&#xff0c;如果我们需要对 PDF 进行更改怎么办&#xff1f; 对 PDF 进行更改通常无法在 PDF 本身上完…

Vue3通透教程【二】更高效的构建工具—Vite

文章目录&#x1f31f; 写在前面&#x1f31f; webpack&#x1f31f; Vite是什么&#xff1f;&#x1f31f; 使用Vite创建项目&#x1f31f; 写在最后&#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更…

【成为架构师课程系列】架构师的核心能力地图

目录 架构师核心能力总结 #综合技术能力分层总结 #数据结构和算法知识图谱总结 #Java工程师【核心基础】知识图谱总结

全栈开发工程师面试题五-Eureka

1.服务的提供者和服务的消费者&#xff08;服务的调用关系&#xff09; 服务的提供者&#xff1a;在一次服务中被其他服务调用的服务(提供接口给其他服务) 服务的消费者&#xff1a;一次业务中调用其他服务的服务&#xff08;调用其它微服务提供的接口&#xff09; 服务的提供者…

Koa2-创建、中间件、连接数据库、处理请求、日志

文章目录安装配置koa2配置nodemon,热更新我们的项目中间件什么是中间件&#x1f47b;洋葱模型路由中间件连接数据库 - mysql后端允许跨域处理请求getpostputdelete后续会继续更新安装配置koa2 &#x1f47b;安装 koa2 npm i koa2 -s&#x1f47b;在package.json 配置,当然是在…

如何在QEMU社区提Bug

当在编译及使用QEMU的过程中发现问题又不能自行解决时&#xff0c;可以去QEMU官网提Bug。本文以笔者实际遇到的问题为例&#xff0c;讲解提交QEMU Bug的完整过程。 1. 访问QEMU主页 QEMU官网主页地址为&#xff1a;https://www.qemu.org/ 页面如下&#xff1a; 2. 跳转至CON…

RK3566 多Mipi屏的兼容

需求:项目需求需要同一个固件兼容两款不同IC的mipi屏。以便有一个IC停产之后使用不受影响。由于是同一个模组厂商,所以设计初就要求硬件接口一样或者兼容。 方法:一开始的想法很简单和网上以及同行提供的方法一样在uboot阶段去读屏的ID,然后再把对应屏ID放到cmdline里面去传…

Parasoft全面发布最广泛的MISRA规则覆盖

Parasoft通过其经过市场验证的自动化软件测试工具集成套件&#xff0c;帮助企业持续交付高质量的软件。Parasoft的技术支持嵌入式、企业和物联网市场&#xff0c;通过将静态代码分析和单元测试、Web UI和API测试等所有内容集成到交付管道中&#xff0c;再加上服务虚拟化和完整的…