type
Post
status
Published
date
Mar 12, 2026
slug
summary
渲染的基本要素
物体的变换
动画
摄影机
摄像机移动
全屏与resize
几何体(Geometry)
debugUI
tags
Three.js
category
技术学习笔记
icon
password
渲染的基本要素
场景
使用
const scene = new THREE.Scene(); 来创建一个场景,用于展示我们创建的物体或引入的建模摄像机
在现实生活中,我们人眼就好比一个摄像机,离一个物体
越近 ,看到的物体就显得 越大 ,反之亦然;当我们把摄像机 向左 移动,就相当于物体 向右 发生了移动,反之亦然。在
threejs 中最基本的相机是透视摄像机 PerspectiveCamera ,实现方式为Copy
第一个参数是
,代表视场角度,单位是
。我们人的眼睛就是一台摄像机,我们在正前方画一条垂直于地面直线,那么必定存在两个点使得点到人眼形成的角度之和为75度,以这个75度角发散出去能看到的范围就是
,如下图

第二个参数是宽高比,从上图可以看到,看出去的视角范围实际上是一个视锥,底部都是矩形的视觉区域,而每个矩形的宽高比必定为指定的宽高比。
网格(mesh)
就可以理解为要在场景中展示的东西了,要生成一个
,需要一个几何体(
)(或自己的3D模型),加上该几何体的
(
)


在这里插入图片描述
Copy
渲染器(renderer)
当我们有了要观察的物体后,就可以把他们渲染到场景上,用摄像机去观察了
renderer 通常使用 WebGLRenderer 来创建,可以在创建 WebGLRenderer 时指定画布 dom 元素Copy
也可以不传该参数,它会默认创建一个
canvas 元素,我们只需要把他添加到页面指定位置即可,如Copy
最后,我们调用
renderer.render 方法就可以把物体和摄像机放到场景中了Copy
但是,这时候在页面上看到的是一片黑,这是为什么呢?

在默认情况下,摄像机、物体都是放在正中心的位置,即
(0, 0, 0) 位置,所以此时相当于我们处于立方体的内部,那么从立方体内部往外看,自然什么都看不到,这时候我们需要把摄像机向后移或者把物体往前移动(也就是在Z轴上移动)即可Copy

在这里插入图片描述
需要注意的是,renderer.render相当于拍了一张照片,任何对于物体的修改或位置的移动,都需要重新执行一次renderer.render(scene, camera);来把场景和摄像机进行更新,即以后要做的动画,就是不断地一帧一帧地把物体实时地位置给渲染出来的过程
物体的变换
位置(position)
对于物体而言,其位置通常指的是它中心的坐标,一些实用的方法如下:
- meth.position.length():获取场景中心点(0, 0, 0)到物体中心的距离,这个其实就可以理解为在空间直角坐标系中两点之间距离的计算
- meth.position.distanceTo(someVector):物体中心到某个矢量点的距离,比如可以传
camera.position来计算摄像机到物体的距离
position 的类型是 Vector3 ,可以在文档中查询 Vector3 包含的所有方法,这里不作列举Axes Helper
拉出一个坐标系参照,可以配置仅在开发环境渲染辅助坐标系
Copy
scale
即缩放,对于下面这个物体

x轴缩放设为0.5时:

x轴缩放设为-0.25时:

可以看到,缩放设为负数并不会有什么特殊的含义,并且缩放也不会改变物体的
position (中心点位置)旋转rotation
旋转需要注意的是,旋转指的是
进行旋转,比如旋转x轴
,那就是以
轴为中线进行旋转,我写了个基本的动画,其旋转的方式如下:

同理,对于Y轴而言就是:

注意这里,旋转时应该使用JS内置的Math.PI常量进行旋转,即圆周率的倍数。当然也不是不能指定一个整数
设置旋转角度、位置、缩放,可以使用
.x = number、.y = number、.z = number 一个一个设置,也可以使用 set 一次性设置3个值组内变换
如果物体多了,一般会给既定的物体分一个组,然后对这整个组进行操作,比如旋转或缩放等

在这里插入图片描述
Copy
动画
通常使用
requestAnimationFrame 来实现,通过在回调函数中不断地重复调用 requestAnimationFrame 来做出动画效果但是在不同设备上,屏幕的刷新率不同,那么
requestAnimationFrame 的执行速度也会不同,同理动画的速度也会不同所以需要兼容不同设备刷新率情况下的动画,此时可以使用
Date.now 来计算实现Copy
此外,threeJS内部也提供了解决方案,使用内置的
Clock 类来实现Copy
Clock会从0开始计时,官网上的实现说的是优先用
实现,然后才是用
实现

那么,有了动画,除了基本的旋转之外,就可以实现比如下面的这些小动画了:
指定每秒旋转一圈:
Copy
因为
getElapsedTime 获取的是秒级单位,所以可以这样子写, 2派 就代表一个圆的直径,那么多少秒就是多少个圆的直径,也就是转多少圈了结合三角函数
三角函数的图像中,
正弦函数随着x增大,其y值呈周期性地变化到1和-1

那么如果我们想让一个物体在Y轴移动出正弦函数曲线,就可以写成:
Copy

在这里插入图片描述
如果想让它转圈,则可以对它的x也做类似地处理,不过呢要用余弦函数
Copy

在这里插入图片描述
使用动画库
GSAP 是一个很牛B的动画库,官网是: https://gsap.com/可以通过使用动画库API,更方便我们实现一些动画(比如直接调用预设)
Copy
可以看到控制台,它的原理就是在一秒内修改x和y分别到3和2,然后在2秒后,在1秒内把x和y分别改到0和-1

摄影机
透视摄像机(Perspective Camera)
前面已经讲了前两个参数,这里只讲后面两个参数
near 和 far两个参数代表的是摄像机最近/最远可见的距离,这两个距离分别指的是
到摄像机(人)和
到摄像机(人)的距离

所以,只有
far-near 之间的阴影部分区域的物体,才可以被看到(即渲染在画布中)near和far的默认值为0.1 - 2000
正交摄像机(Orthographic Camera)
正交摄像机没有透视功能,他与透视摄像机最大的区别是”不会有
近大远小 “的效果,接收的参数是 (左,右,上,下,近距,远距)拿一个
举例,透视相机从正前方和侧面看一个物体是这样:

相机位置:(0, 0, 3);物体位置:(0, 0, 0)

在这里插入图片描述
相机位置:(2, 1, 3);物体位置:(0, 0, 0);
当换成正交相机时,从正前方看,看到的图像是:

代码设置如下:
Copy
测试会发现,无论怎么移动摄像机
Z轴 位置,看到的物体没有任何变化移动X、Y轴位置,则是进行”左右” 或 “上下”的平移
代码表示的是,创建一个长宽均为
2 的正方形视框去观察画面中的物体对于上面的例子,创建的物体是中心为
(0, 0, 0) ,长宽高均为1的正方体Copy
刚刚把正交相机往正前方移动了3个单位长度,那么可以想到目前
摄像机到物体正面 的距离为 3 - 0.5 = 2.5假如把正交摄像机的近距设为
> 2.5 的值,那么就会看不到物体的正面了,比如把正交相机改为下面这样:Copy
此时画面显示为:

因为我们此时恰好深入到了物体的内部
0.01 的位置,从物体里往外看自然看不到物体本身摄像机移动
基本的实现原理是,监听鼠标移动事件,记录鼠标的
clientX 与 clientY ,使用这俩修改摄像机的 position 即可手动实现
添加监听:
Copy
注意这里的Y轴在前面加了负号,因为在Y轴是向上为负,向下为正
同步相机运动:
Copy
实际效果:

在这里插入图片描述
这种情况下相当于只移动摄像机,摄像机的视角为正前方
如果让摄像机始终看向原点(即
),则实际效果为:

OrbitControl
threejs 内置了各种 control 对象,比如 OrbitControl 便可用来实现丝滑的移动和缩放等操作,它接收两个参数 camera 和 domElement ;camera 即摄像机对象, domElement 一般传的是渲染出来的 renderElement ,所以它内部实际上就是监听 mousemove 等事件来实现操控的这个
control 应该是未来最常用 control 了其他相关的配置就自己看文档了
ArcballControls
中文叫弧球控制器,主要是可以让用户以一个球状的视角对物体进行操作,支持双击缩放;使用时不需要在
animate 中重复调用 render 方法或 controls.update() 方法渲染DragControls
拖放控制器,用来给某个物体添加拖拽交互,这个拖拽包括移动和渲染,通过
controls.mode 设置;第一个参数接收一个支持操作的物体数组(比如 mesh 数组)FirstPersonControls
第一人称控制器,名副其实,可以用来模拟一个第一人称视角下的移动等操作,
lookSpeed 、 movementSpeed 分别控制垂直和水平方向的移动(需要注意速度值的设置);需要注意的是,要在动画中添加 controls.update 来使其生效Copy
FlyControls
飞行控制器,默认情况下,通过
进行前后左右平移,
进行上下平移,
旋转视角,
控制摄像机视角;需要在
中持续调用
方法来实现

使用时注意
speed 相关值的设置,尽量不设置太大(除非场景本身就可以到达很远)Copy
全屏与resize
resize 通过监听浏览器 resize 事件实现,更新时,需要同时更新两个要素- 摄像机长宽比
aspect
- 渲染器
renderer的尺寸
Copy
关键的方法是
camera.updateProjectionMatrix(); 和 renderer.setSize(sizes.width, sizes.height);这里的
pixelRatio 指的是像素比,在PC上通常不需要超过2的像素比,越高的像素比对于 GPU 的要求则越高,同时也意味着渲染出来的画质越好下面这是一块电脑屏幕,像素比为1时,对应着第一格;像素比为2时,意味着在原先一格的基础上再将其分为4个像素,以此类推:

全屏的设置,主要通过
requestFullscreen API来实现,需要注意的是 IOS 上的API有所不同(webkitRequestFullscreen)Copy
几何体(Geometry)
threejs 中的几何体非常丰富,每个几何体在空间中由多个”顶点”连线而成点构成线,线构成面,面最终画出几何体

所有的
threejs 几何体都继承自 BufferGeometry 类,使得他们拥有相似的属性如 position 、 width 、 height 等每个面都是由N个三角形构成的
拿
举例,前6个参数分别为:

segments 的设置,1就是两个三角形,2就是从上和下的中点各延申一条直线将平面分为4等分,每个“小面”都分成两个三角形,最终就得到了8个三角形,以此类推创建几何体时,可以通过设置
wireFrame: true 来查看几何体每个面的三角形Copy

在这里插入图片描述
可以想一下实景3D地图,在一个平铺的3D地图种,他是怎么画出来凹凸不平的山峦效果的?

在这里插入图片描述
实际上就是每个面上有多个相交的顶点时,我们就可以控制这些顶点的位置,比如让他在Z轴上抬高几个距离,其他点跟他一连线即可构成
凸起 的效果
在这里插入图片描述
自己创建几何体
- 创建一个
float32Array
- 使用该
array构建一个bufferAttribute
- 创建一个
bufferGeometry并给该缓冲几何体设置attribute(使用setAttribute方法)
- 创建材质,创建网格,添加网格
Copy

在这里插入图片描述

在这里插入图片描述
float32Array
也可以用这个方法创建一堆三角形置于空间中
Copy

在这里插入图片描述
debugUI
每次在代码里修改并且看效果并不是最效率的调试方法,所以建议使用的是
lil-gui ,因为它的生态比较完善,并且比较轻量通过
npm i lil-gui 进行安装官方文档地址:
https://lil-gui.georgealways.com/#GUI全称是
Graphical User Interface ,这个不是专门为 threejs 而诞生的,它本质是操作一个对象的属性,使用起来很简单,通过 .add 方法来添加一个操控Copy

在这里插入图片描述
渲染的基本要素
场景
使用
const scene = new THREE.Scene(); 来创建一个场景,用于展示我们创建的物体或引入的建模摄像机
在现实生活中,我们人眼就好比一个摄像机,离一个物体
越近 ,看到的物体就显得 越大 ,反之亦然;当我们把摄像机 向左 移动,就相当于物体 向右 发生了移动,反之亦然。在
threejs 中最基本的相机是透视摄像机 PerspectiveCamera ,实现方式为Copy
第一个参数是
,代表视场角度,单位是
。我们人的眼睛就是一台摄像机,我们在正前方画一条垂直于地面直线,那么必定存在两个点使得点到人眼形成的角度之和为75度,以这个75度角发散出去能看到的范围就是
,如下图

第二个参数是宽高比,从上图可以看到,看出去的视角范围实际上是一个视锥,底部都是矩形的视觉区域,而每个矩形的宽高比必定为指定的宽高比。
网格(mesh)
就可以理解为要在场景中展示的东西了,要生成一个
,需要一个几何体(
)(或自己的3D模型),加上该几何体的
(
)


在这里插入图片描述
Copy
渲染器(renderer)
当我们有了要观察的物体后,就可以把他们渲染到场景上,用摄像机去观察了
renderer 通常使用 WebGLRenderer 来创建,可以在创建 WebGLRenderer 时指定画布 dom 元素Copy
也可以不传该参数,它会默认创建一个
canvas 元素,我们只需要把他添加到页面指定位置即可,如Copy
最后,我们调用
renderer.render 方法就可以把物体和摄像机放到场景中了Copy
但是,这时候在页面上看到的是一片黑,这是为什么呢?

在默认情况下,摄像机、物体都是放在正中心的位置,即
(0, 0, 0) 位置,所以此时相当于我们处于立方体的内部,那么从立方体内部往外看,自然什么都看不到,这时候我们需要把摄像机向后移或者把物体往前移动(也就是在Z轴上移动)即可Copy

在这里插入图片描述
需要注意的是,renderer.render相当于拍了一张照片,任何对于物体的修改或位置的移动,都需要重新执行一次renderer.render(scene, camera);来把场景和摄像机进行更新,即以后要做的动画,就是不断地一帧一帧地把物体实时地位置给渲染出来的过程
物体的变换
位置(position)
对于物体而言,其位置通常指的是它中心的坐标,一些实用的方法如下:
- meth.position.length():获取场景中心点(0, 0, 0)到物体中心的距离,这个其实就可以理解为在空间直角坐标系中两点之间距离的计算
- meth.position.distanceTo(someVector):物体中心到某个矢量点的距离,比如可以传
camera.position来计算摄像机到物体的距离
position 的类型是 Vector3 ,可以在文档中查询 Vector3 包含的所有方法,这里不作列举Axes Helper
拉出一个坐标系参照,可以配置仅在开发环境渲染辅助坐标系
Copy
scale
即缩放,对于下面这个物体

x轴缩放设为0.5时:

x轴缩放设为-0.25时:

可以看到,缩放设为负数并不会有什么特殊的含义,并且缩放也不会改变物体的
position (中心点位置)旋转rotation
旋转需要注意的是,旋转指的是
进行旋转,比如旋转x轴
,那就是以
轴为中线进行旋转,我写了个基本的动画,其旋转的方式如下:

同理,对于Y轴而言就是:

注意这里,旋转时应该使用JS内置的Math.PI常量进行旋转,即圆周率的倍数。当然也不是不能指定一个整数
设置旋转角度、位置、缩放,可以使用
.x = number、.y = number、.z = number 一个一个设置,也可以使用 set 一次性设置3个值组内变换
如果物体多了,一般会给既定的物体分一个组,然后对这整个组进行操作,比如旋转或缩放等

在这里插入图片描述
Copy
动画
通常使用
requestAnimationFrame 来实现,通过在回调函数中不断地重复调用 requestAnimationFrame 来做出动画效果但是在不同设备上,屏幕的刷新率不同,那么
requestAnimationFrame 的执行速度也会不同,同理动画的速度也会不同所以需要兼容不同设备刷新率情况下的动画,此时可以使用
Date.now 来计算实现Copy
此外,threeJS内部也提供了解决方案,使用内置的
Clock 类来实现Copy
Clock会从0开始计时,官网上的实现说的是优先用
实现,然后才是用
实现

那么,有了动画,除了基本的旋转之外,就可以实现比如下面的这些小动画了:
指定每秒旋转一圈:
Copy
因为
getElapsedTime 获取的是秒级单位,所以可以这样子写, 2派 就代表一个圆的直径,那么多少秒就是多少个圆的直径,也就是转多少圈了结合三角函数
三角函数的图像中,
正弦函数随着x增大,其y值呈周期性地变化到1和-1

那么如果我们想让一个物体在Y轴移动出正弦函数曲线,就可以写成:
Copy

在这里插入图片描述
如果想让它转圈,则可以对它的x也做类似地处理,不过呢要用余弦函数
Copy

在这里插入图片描述
使用动画库
GSAP 是一个很牛B的动画库,官网是: https://gsap.com/可以通过使用动画库API,更方便我们实现一些动画(比如直接调用预设)
Copy
可以看到控制台,它的原理就是在一秒内修改x和y分别到3和2,然后在2秒后,在1秒内把x和y分别改到0和-1

摄影机
透视摄像机(Perspective Camera)
前面已经讲了前两个参数,这里只讲后面两个参数
near 和 far两个参数代表的是摄像机最近/最远可见的距离,这两个距离分别指的是
到摄像机(人)和
到摄像机(人)的距离

所以,只有
far-near 之间的阴影部分区域的物体,才可以被看到(即渲染在画布中)near和far的默认值为0.1 - 2000
正交摄像机(Orthographic Camera)
正交摄像机没有透视功能,他与透视摄像机最大的区别是”不会有
近大远小 “的效果,接收的参数是 (左,右,上,下,近距,远距)拿一个
举例,透视相机从正前方和侧面看一个物体是这样:

相机位置:(0, 0, 3);物体位置:(0, 0, 0)

在这里插入图片描述
相机位置:(2, 1, 3);物体位置:(0, 0, 0);
当换成正交相机时,从正前方看,看到的图像是:

代码设置如下:
Copy
测试会发现,无论怎么移动摄像机
Z轴 位置,看到的物体没有任何变化移动X、Y轴位置,则是进行”左右” 或 “上下”的平移
代码表示的是,创建一个长宽均为
2 的正方形视框去观察画面中的物体对于上面的例子,创建的物体是中心为
(0, 0, 0) ,长宽高均为1的正方体Copy
刚刚把正交相机往正前方移动了3个单位长度,那么可以想到目前
摄像机到物体正面 的距离为 3 - 0.5 = 2.5假如把正交摄像机的近距设为
> 2.5 的值,那么就会看不到物体的正面了,比如把正交相机改为下面这样:Copy
此时画面显示为:

因为我们此时恰好深入到了物体的内部
0.01 的位置,从物体里往外看自然看不到物体本身摄像机移动
基本的实现原理是,监听鼠标移动事件,记录鼠标的
clientX 与 clientY ,使用这俩修改摄像机的 position 即可手动实现
添加监听:
Copy
注意这里的Y轴在前面加了负号,因为在Y轴是向上为负,向下为正
同步相机运动:
Copy
实际效果:

在这里插入图片描述
这种情况下相当于只移动摄像机,摄像机的视角为正前方
如果让摄像机始终看向原点(即
),则实际效果为:

OrbitControl
threejs 内置了各种 control 对象,比如 OrbitControl 便可用来实现丝滑的移动和缩放等操作,它接收两个参数 camera 和 domElement ;camera 即摄像机对象, domElement 一般传的是渲染出来的 renderElement ,所以它内部实际上就是监听 mousemove 等事件来实现操控的这个
control 应该是未来最常用 control 了其他相关的配置就自己看文档了
ArcballControls
中文叫弧球控制器,主要是可以让用户以一个球状的视角对物体进行操作,支持双击缩放;使用时不需要在
animate 中重复调用 render 方法或 controls.update() 方法渲染DragControls
拖放控制器,用来给某个物体添加拖拽交互,这个拖拽包括移动和渲染,通过
controls.mode 设置;第一个参数接收一个支持操作的物体数组(比如 mesh 数组)FirstPersonControls
第一人称控制器,名副其实,可以用来模拟一个第一人称视角下的移动等操作,
lookSpeed 、 movementSpeed 分别控制垂直和水平方向的移动(需要注意速度值的设置);需要注意的是,要在动画中添加 controls.update 来使其生效Copy
FlyControls
飞行控制器,默认情况下,通过
进行前后左右平移,
进行上下平移,
旋转视角,
控制摄像机视角;需要在
中持续调用
方法来实现

使用时注意
speed 相关值的设置,尽量不设置太大(除非场景本身就可以到达很远)Copy
全屏与resize
resize 通过监听浏览器 resize 事件实现,更新时,需要同时更新两个要素- 摄像机长宽比
aspect
- 渲染器
renderer的尺寸
Copy
关键的方法是
camera.updateProjectionMatrix(); 和 renderer.setSize(sizes.width, sizes.height);这里的
pixelRatio 指的是像素比,在PC上通常不需要超过2的像素比,越高的像素比对于 GPU 的要求则越高,同时也意味着渲染出来的画质越好下面这是一块电脑屏幕,像素比为1时,对应着第一格;像素比为2时,意味着在原先一格的基础上再将其分为4个像素,以此类推:

全屏的设置,主要通过
requestFullscreen API来实现,需要注意的是 IOS 上的API有所不同(webkitRequestFullscreen)Copy
几何体(Geometry)
threejs 中的几何体非常丰富,每个几何体在空间中由多个”顶点”连线而成点构成线,线构成面,面最终画出几何体

所有的
threejs 几何体都继承自 BufferGeometry 类,使得他们拥有相似的属性如 position 、 width 、 height 等每个面都是由N个三角形构成的
拿
举例,前6个参数分别为:

segments 的设置,1就是两个三角形,2就是从上和下的中点各延申一条直线将平面分为4等分,每个“小面”都分成两个三角形,最终就得到了8个三角形,以此类推创建几何体时,可以通过设置
wireFrame: true 来查看几何体每个面的三角形Copy

在这里插入图片描述
可以想一下实景3D地图,在一个平铺的3D地图种,他是怎么画出来凹凸不平的山峦效果的?

在这里插入图片描述
实际上就是每个面上有多个相交的顶点时,我们就可以控制这些顶点的位置,比如让他在Z轴上抬高几个距离,其他点跟他一连线即可构成
凸起 的效果
在这里插入图片描述
自己创建几何体
- 创建一个
float32Array
- 使用该
array构建一个bufferAttribute
- 创建一个
bufferGeometry并给该缓冲几何体设置attribute(使用setAttribute方法)
- 创建材质,创建网格,添加网格
Copy

在这里插入图片描述

在这里插入图片描述
float32Array
也可以用这个方法创建一堆三角形置于空间中
Copy

在这里插入图片描述
debugUI
每次在代码里修改并且看效果并不是最效率的调试方法,所以建议使用的是
lil-gui ,因为它的生态比较完善,并且比较轻量通过
npm i lil-gui 进行安装官方文档地址:
https://lil-gui.georgealways.com/#GUI全称是
Graphical User Interface ,这个不是专门为 threejs 而诞生的,它本质是操作一个对象的属性,使用起来很简单,通过 .add 方法来添加一个操控Copy

在这里插入图片描述

