1. Three.js 入门:从零搭建你的第一个3D场景
大家好,我是老张。今天咱们聊聊 Three.js 入门。说实话,我第一次接触 Three.js 的时候,心里也犯嘀咕——这玩意儿到底能干啥?后来在几个项目里摸爬滚打,才慢慢摸清了门道。嗯,今天就把这些经验分享给你。
1.1 Three.js 是什么?
Three.js 是一个基于 WebGL 的 JavaScript 3D 库。说白了,它帮你把复杂的 WebGL 底层操作封装成了简单好用的 API。你不需要懂图形学里的矩阵变换、着色器编程,就能在浏览器里搞出酷炫的 3D 效果。
我个人习惯把它比作「3D 界的 jQuery」。WebGL 就像原生 JavaScript,功能强大但写起来费劲。Three.js 就像 jQuery,让你用几行代码搞定原本几十行的事。
核心特点:
- 开源免费,社区活跃
- 支持所有主流浏览器(包括移动端)
- 内置了场景、相机、渲染器、灯光、材质等完整体系
- 可以加载各种 3D 模型格式(glTF、OBJ、FBX 等)
我在项目中遇到过不少用 Three.js 做的案例:产品展示页、数据可视化大屏、甚至一个简单的室内漫游 demo。你想想看,一个网页就能跑 3D,多方便。
1.2 三大核心概念:场景、相机、渲染器
Three.js 的架构其实特别简单,就三个核心东西:场景(Scene)、相机(Camera)、渲染器(Renderer)。这三者缺一不可,就像拍电影需要舞台、摄像机和放映机一样。
1.2.1 场景(Scene)
场景就是你的 3D 世界。所有物体、灯光、辅助线都放在里面。你可以把它想象成一个空房间,你往里面放什么,它就有什么。
const scene = new THREE.Scene();
就这么一行,一个空场景就建好了。然后你可以往里面加东西:
// 加一个立方体
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);
小技巧: 我习惯在场景里加一个网格辅助线(GridHelper),方便观察物体的位置和方向。尤其是调试的时候,这东西帮了大忙。
1.2.2 相机(Camera)
相机决定了你从哪个角度观察场景。Three.js 提供了好几种相机,最常用的是 透视相机(PerspectiveCamera) 和 正交相机(OrthographicCamera)。
透视相机模拟人眼效果——近大远小。正交相机则没有透视效果,适合做 2D 或等轴测图。
// 透视相机:视野75度,宽高比自适应,近裁面0.1,远裁面1000
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5); // 把相机往后拉一点
camera.lookAt(0, 0, 0); // 看向原点
这里要注意几个参数:
| 参数 | 说明 | 我的建议 |
|---|---|---|
| FOV(视野) | 视角宽度,单位度 | 一般 45-75 之间,太宽会变形 |
| 宽高比 | 画面宽度/高度 | 用 window.innerWidth / window.innerHeight |
| 近裁面/远裁面 | 可见范围 | 近裁面别设太小,远裁面别设太大 |
避坑指南: 我曾经把近裁面设成了 0.001,远裁面设成了 100000。结果场景里有些物体莫名其妙消失了,查了半天才发现是精度问题。建议近裁面 0.1,远裁面 1000 就够用。
1.2.3 渲染器(Renderer)
渲染器负责把场景和相机的内容画到屏幕上。最常用的是 WebGLRenderer。
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
渲染器会创建一个 canvas 元素,你把它挂到页面上就行。然后每帧调用:
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
嗯,这里要注意:渲染器一定要在场景和相机都准备好之后才调用 render。不然你会看到一个黑屏,啥也没有。
1.3 搭建第一个 Three.js 场景
好了,理论说完了,咱们动手写一个完整的例子。这个场景里有一个旋转的立方体,背景是浅蓝色。
<!DOCTYPE html>
<html>
<head>
<title>我的第一个Three.js场景</title>
<style>
body { margin: 0; overflow: hidden; }
</style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// 1. 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // 浅蓝色
// 2. 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
camera.lookAt(0, 0, 0);
// 3. 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. 添加一个立方体
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);
// 5. 添加网格辅助线(方便观察)
const gridHelper = new THREE.GridHelper(10, 10);
scene.add(gridHelper);
// 6. 动画循环
function animate() {
requestAnimationFrame(animate);
// 让立方体旋转
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
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>
个人经验: 我刚开始写 Three.js 时,经常忘记加 camera.updateProjectionMatrix()。窗口缩放后画面就变形了。记住:改了相机宽高比,一定要调用这个方法。
运行这段代码,你会看到一个浅蓝色背景的 3D 场景,中间有一个绿色立方体在慢慢旋转。底部还有网格线帮你定位。
你想想看,就这么几行代码,一个 3D 场景就跑起来了。是不是比想象中简单?
1.4 本章小结
今天我们干了三件事:
- 认识了 Three.js——一个让 WebGL 变得简单的 3D 库
- 理解了三大核心——场景(装东西)、相机(看东西)、渲染器(画东西)
- 亲手搭了一个场景——带旋转立方体的 3D 页面
下一章我们会深入聊聊场景里的物体和材质。到时候我会分享一些我在实际项目中踩过的坑,比如材质不显示、模型加载失败之类的。嗯,敬请期待。
公众号:蓝海资料掘金营,微信deep3321