01 Three.js 入门
学习创建第一个 Three.js 3D 场景
安装 Three.js
方式一:CDN(推荐学习使用)
html
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js'
</script>1
2
3
2
3
方式二:npm 安装
bash
pnpm add three1
js
import * as THREE from 'three'1
三个核心概念
Three.js 的核心就是三样东西:场景(Scene)、相机(Camera)、渲染器(Renderer)。
相机拍摄 ──→ 渲染器把画面绘制到屏幕
↑
场景(放置所有 3D 物体)1
2
3
2
3
创建场景
js
import * as THREE from 'three'
// 创建场景
const scene = new THREE.Scene()
// 设置背景色
scene.background = new THREE.Color(0x1a1a2e)
// 添加雾效(远处物体渐变消失)
scene.fog = new THREE.Fog(0x1a1a2e, 10, 50)1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
创建相机
相机决定了我们"从哪个角度"观察场景。
透视相机(最常用)
模拟人眼的视觉效果,远处的物体看起来更小。
js
// 透视相机
const camera = new THREE.PerspectiveCamera(
75, // 视野角度(FOV),越大看到越多
window.innerWidth / window.innerHeight, // 宽高比
0.1, // 近裁切面(太近的物体不显示)
1000 // 远裁切面(太远的物体不显示)
)
// 相机位置(x, y, z)
camera.position.set(0, 0, 5)
// 相机朝向(默认朝向 -z 轴方向)
camera.lookAt(0, 0, 0)1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
正交相机
物体大小固定,不受距离影响,适合 2D UI 或建筑图纸。
js
const aspect = window.innerWidth / window.innerHeight
const frustumSize = 10
const camera = new THREE.OrthographicCamera(
-frustumSize * aspect / 2, // 左边界
frustumSize * aspect / 2, // 右边界
frustumSize / 2, // 上边界
-frustumSize / 2, // 下边界
0.1, // 近裁切面
1000 // 远裁切面
)1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
创建渲染器
渲染器负责把 3D 场景绘制成 2D 图像显示在屏幕上。
js
// 创建 WebGL 渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true // 开启抗锯齿,让边缘更平滑
})
// 设置渲染尺寸
renderer.setSize(window.innerWidth, window.innerHeight)
// 支持高清屏(适配不同设备像素比)
renderer.setPixelRatio(window.devicePixelRatio)
// 将 Canvas 添加到页面
document.body.appendChild(renderer.domElement)1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
创建 3D 物体
立方体
js
// 创建几何体(Geometry)
const geometry = new THREE.BoxGeometry(1, 1, 1)
// 创建材质(Material)
const material = new THREE.MeshStandardMaterial({
color: 0xff6b6b, // 红色
roughness: 0.5, // 粗糙度(0=光滑,1=粗糙)
metalness: 0.3 // 金属度(0=非金属,1=金属)
})
// 创建网格(Mesh)= 几何体 + 材质
const cube = new THREE.Mesh(geometry, material)
// 添加到场景
scene.add(cube)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
球体
js
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32) // 半径1,32段
const sphereMaterial = new THREE.MeshStandardMaterial({
color: 0x4ecdc4,
roughness: 0.3,
metalness: 0.1
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
其他常用几何体
js
// 平面(常用于地面)
const plane = new THREE.PlaneGeometry(10, 10)
// 圆柱体
const cylinder = new THREE.CylinderGeometry(0.5, 0.5, 2, 32)
// 圆环
const torus = new THREE.TorusGeometry(1, 0.3, 16, 100)
// 圆锥
const cone = new THREE.ConeGeometry(1, 2, 32)1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
添加光照
没有光照,你只能看到黑色物体。光照让物体有了立体感。
环境光
均匀照亮所有物体,不会产生阴影。
js
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4)
scene.add(ambientLight)1
2
2
平行光(太阳光)
光线平行照射,可以产生阴影。
js
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
directionalLight.position.set(5, 5, 5) // 光照方向
scene.add(directionalLight)1
2
3
2
3
动画循环
用 requestAnimationFrame 实现动画。
js
function animate() {
requestAnimationFrame(animate)
// 每帧旋转一点(绕 Y 轴)
cube.rotation.y += 0.01
cube.rotation.x += 0.005
// 用渲染器绘制场景
renderer.render(scene, camera)
}
animate()1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
完整示例
html
<!DOCTYPE html>
<html>
<head>
<title>Three.js 第一个场景</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js'
// 1. 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x1a1a2e)
// 2. 创建相机
const camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.1, 1000
)
camera.position.z = 5
// 3. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(window.devicePixelRatio)
document.body.appendChild(renderer.domElement)
// 4. 创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({ color: 0xff6b6b })
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
// 5. 添加光照
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
directionalLight.position.set(5, 5, 5)
scene.add(directionalLight)
// 6. 动画循环
function animate() {
requestAnimationFrame(animate)
cube.rotation.y += 0.01
cube.rotation.x += 0.005
renderer.render(scene, camera)
}
animate()
// 7. 响应窗口大小变化
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
</script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
调试技巧
AxesHelper(坐标轴辅助线)
显示 X(红)、Y(绿)、Z(蓝)三个轴,帮助理解方向。
js
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)1
2
2
GridHelper(网格辅助线)
显示地面网格。
js
const gridHelper = new THREE.GridHelper(10, 10)
scene.add(gridHelper)1
2
2
坐标系说明
Three.js 使用右手坐标系:
Y (上)
↑
│
│
│
└────────→ X (右)
↙
Z (朝向你/屏幕外)1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
| 方向 | 正值 |
|---|---|
| X | 右 |
| Y | 上 |
| Z | 朝向观察者(屏幕外) |
物体位置参数
js
// 直接设置
cube.position.x = 2
cube.position.y = 1
cube.position.z = -3
// 或者一次性设置
cube.position.set(2, 1, -3)
// 也可以用向量
cube.position = new THREE.Vector3(2, 1, -3)1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
旋转(弧度制)
Three.js 使用弧度而非角度:
js
// 180° = π 弧度
// 90° = π/2 弧度
cube.rotation.x = Math.PI / 4 // 45°
cube.rotation.y = Math.PI / 2 // 90°
cube.rotation.z = Math.PI // 180°
// 度数转弧度
const degrees = 45
const radians = degrees * (Math.PI / 180)1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10