主题
03 · Three.js:从零到可演示小场景
目标:能口述场景 / 相机 / 渲染器 / 网格;浏览器里跑出可交互的一小段 3D;记住 3 条常见坑。
官方:three.js docs · manual
1. 背景与目标
Three.js 是作品集与面试里少见的「可演示亮点」:你不只会 CRUD,还能讲一点渲染管线直觉。本篇不追特效,只求最小可演示闭环。
2. 核心概念(一张图说完)
text
Scene(装物体)
+ Camera(从哪看)
+ Mesh = Geometry(形状)+ Material(外观)
+ Light(可选但常需要)
│
▼
Renderer.render(scene, camera) ← 每帧画一次1
2
3
4
5
6
7
2
3
4
5
6
7
| 概念 | 一句话 |
|---|---|
| Scene | 世界容器 |
| PerspectiveCamera | 透视相机;fov / aspect / near / far |
| WebGLRenderer | 画到 <canvas> |
| Mesh | 可渲染物体 |
| Animation loop | requestAnimationFrame 里改变换再 render |
3. 最小实践:旋转立方体
用 Vite 或纯 HTML 均可。核心代码:
js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x111111)
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 100)
camera.position.set(2, 2, 3)
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(innerWidth, innerHeight)
renderer.setPixelRatio(Math.min(devicePixelRatio, 2))
document.body.appendChild(renderer.domElement)
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0x4ea1ff })
)
scene.add(mesh)
const light = new THREE.DirectionalLight(0xffffff, 1.2)
light.position.set(3, 5, 2)
scene.add(light)
scene.add(new THREE.AmbientLight(0xffffff, 0.35))
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
function tick() {
mesh.rotation.y += 0.01
controls.update()
renderer.render(scene, camera)
requestAnimationFrame(tick)
}
tick()
addEventListener('resize', () => {
camera.aspect = innerWidth / innerHeight
camera.updateProjectionMatrix()
renderer.setSize(innerWidth, innerHeight)
})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
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
进阶一步(可选):用 GLTFLoader 加载一个小模型,路径注意打包后的 public/。
4. 踩坑与取舍(至少记 3 条)
- 忘记 dispose:换场景 / 卸载组件时释放
geometry/material/texture/renderer,否则泄漏。 - 坐标系与单位:Y 朝上;模型可能巨大或极小,先
Box3看包围盒再缩放。 - 移动端性能:降
pixelRatio、少开阴影、少 draw call;别一上来全开后处理。 - (加分)与 Vue/React 共存:把 canvas 生命周期绑在
onMounted/useEffect,卸载必停 loop。
取舍:要「炫技粒子」不如先保证 60fps 可旋转的干净场景 能讲清。
5. 验收清单
- [ ] 能画出 Scene / Camera / Renderer / Mesh 关系
- [ ] 本机浏览器里立方体能转,拖动可环视(OrbitControls)
- [ ] 笔记里写下至少 3 条踩坑(dispose / 坐标 / 性能 任选)
- [ ] (可选)加载过一个 GLTF 或换过材质
6. 下一步
→ 04 · 前端工程化:Vite、分包、Tree-shaking
可视化继续加深见 12 · WebGL 与 Shader。
