1. Three.js快速入门指南:从零构建你的第一个3D场景
上周团队接了个可视化大屏项目,甲方要求用WebGL实现动态3D效果。当我打开原生WebGL API文档时,那些晦涩的着色器代码和矩阵运算直接劝退——直到发现了Three.js这个宝藏库。作为深耕前端领域8年的老司机,今天就带大家用最短路径掌握这个让3D开发变简单的神奇工具。
Three.js本质上是对WebGL的友好封装,就像jQuery之于原生DOM操作。它用JavaScript对象抽象了相机、光源、几何体等概念,开发者只需关注业务逻辑而非图形学细节。最新统计显示,全球78%的网页3D项目都基于此库开发,连GitHub的3D文件预览功能都依赖它实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与基础概念
2.1 五分钟快速初始化
新建项目文件夹后,推荐使用Vite构建工具(比Webpack配置更简单):
bash复制npm create vite@latest threejs-demo --template vanilla
cd threejs-demo
npm install three
基础HTML结构只需一个canvas容器:
html复制<div id="canvas-container" style="width: 100vw; height: 100vh;"></div>
<script type="module" src="/main.js"></script>
2.2 核心三要素解析
每个Three.js场景都离不开这三个对象:
- 场景(Scene) - 3D世界的容器,相当于摄影棚
- 相机(Camera) - 观察视角,常用透视相机(PerspectiveCamera)
- 渲染器(Renderer) - 把3D场景绘制到2D画布的工具
初始化代码模板:
javascript复制import * as THREE from 'three'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
75, // 视场角(FOV)
window.innerWidth / window.innerHeight, // 宽高比
0.1, // 近裁剪面
1000 // 远裁剪面
)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
3. 创建你的第一个3D物体
3.1 几何体与材质组合
立方体是最佳入门选择,需要同时定义:
- BoxGeometry:长宽高分别为1单位的立方体
- MeshBasicMaterial:基础材质(不受光照影响)
- Mesh:将几何体与材质结合的可渲染对象
javascript复制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 // 相机后退避免物体被裁剪
3.2 动画循环实现
通过requestAnimationFrame实现60FPS流畅动画:
javascript复制function animate() {
requestAnimationFrame(animate)
cube.rotation.x += 0.01
cube.rotation.y += 0.01
renderer.render(scene, camera)
}
animate()
4. 场景进阶配置技巧
4.1 真实光照系统
替换MeshBasicMaterial为受光照影响的MeshStandardMaterial:
javascript复制const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 })
scene.add(new THREE.AmbientLight(0x404040)) // 环境光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
directionalLight.position.set(1, 1, 1)
scene.add(directionalLight)
4.2 加载外部3D模型
GLTF格式是Three.js官方推荐模型格式:
javascript复制import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
const loader = new GLTFLoader()
loader.load('model.glb', (gltf) => {
scene.add(gltf.scene)
}, undefined, (error) => {
console.error('模型加载失败:', error)
})
常见坑点:GLB模型显示全黑通常是因为没有添加光源,或材质需要开启envMap环境贴图
5. 性能优化与调试
5.1 内存管理三大原则
- 移除场景对象时调用
dispose()释放GPU内存 - 大型场景使用Octree空间分割
- 静态模型尽量合并BufferGeometry
5.2 实用调试工具
javascript复制import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
const controls = new OrbitControls(camera, renderer.domElement)
// 添加坐标轴辅助
scene.add(new THREE.AxesHelper(5))
6. 项目实战:3D产品展示页
最近完成的智能手表展示页核心代码:
javascript复制// 创建产品模型
const watch = await loadModel('watch.glb')
watch.scale.set(0.5, 0.5, 0.5)
// 旋转展示动画
function animate() {
watch.rotation.y += 0.005
renderer.render(scene, camera)
}
// 点击事件切换表盘颜色
document.addEventListener('click', (event) => {
const intersects = raycaster.intersectObjects([watch])
if (intersects.length) {
watch.material.color.setHex(Math.random() * 0xffffff)
}
})
7. 学习资源推荐
- 官方文档:threejs.org(中文文档需注意版本匹配)
- 案例库:threejs-examples.com
- 模型资源:sketchfab.com(选择CC0协议模型)
- 着色器学习:The Book of Shaders
刚开始接触3D开发时,我被NDC坐标系统搞得头晕眼花。后来发现Three.js的Vector3类提供了便捷的坐标转换方法:
javascript复制const ndc = new THREE.Vector3(0.5, 0.5, 0).unproject(camera)
