1. 环境准备:从零搭建Three.js开发环境
第一次接触Three.js时,最让人头疼的就是环境配置。我刚开始学习时,花了大半天时间才把开发环境跑起来。现在回想起来,其实只需要几个简单步骤就能搞定。
1.1 安装Node.js和npm
Three.js的开发离不开Node.js环境。如果你还没安装,可以去Node.js官网下载LTS版本。安装完成后,打开终端输入以下命令检查是否安装成功:
node -v npm -v我建议使用nvm来管理Node.js版本,这样可以在不同项目间切换版本。特别是在团队协作时,能避免"在我机器上能跑"的问题。
1.2 创建项目目录
找个你喜欢的位置,新建一个项目文件夹。我习惯用VSCode开发,所以直接右键在终端打开:
mkdir threejs-starter cd threejs-starter npm init -y这个命令会生成package.json文件,记录项目依赖和配置。接下来我们要安装Three.js核心库。
1.3 安装Three.js
现在安装Three.js非常简单,只需要一行命令:
npm install three --save安装完成后,你会在node_modules文件夹下找到three模块。我建议同时安装几个常用辅助工具:
npm install dat.gui stats.js --save-devdat.gui可以创建可视化控制面板,stats.js能显示性能指标,对调试很有帮助。
2. 开发服务器配置
2.1 选择开发服务器
Three.js项目需要运行在服务器环境下。我测试过几种方案:
- live-server:轻量级,适合快速原型开发
- webpack-dev-server:功能强大,适合复杂项目
- Vite:启动快,热更新灵敏
新手我推荐用live-server,安装简单:
npm install -g live-server2.2 配置启动脚本
在package.json中添加启动命令:
"scripts": { "start": "live-server --port=3000", "dev": "vite" }这样只需运行npm start就能启动开发服务器。我习惯用3000端口,避免和其他服务冲突。
2.3 解决常见问题
第一次运行时可能会遇到跨域问题。这是因为Three.js加载资源需要正确配置CORS。解决方法是在项目根目录创建server.js:
const express = require('express') const app = express() app.use(express.static('public')) app.listen(3000, () => console.log('Server running on port 3000'))然后通过node server.js启动,比live-server更灵活。
3. 创建第一个3D场景
3.1 HTML基础结构
新建index.html文件,基本结构如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My First Three.js Scene</title> <style> body { margin: 0; } canvas { display: block; } </style> </head> <body> <script src="./src/main.js" type="module"></script> </body> </html>注意script标签的type="module",这是现代JavaScript的模块化写法。
3.2 核心三要素:场景、相机、渲染器
在src/main.js中,我们先创建Three.js的三大核心对象:
import * as THREE from 'three' // 1. 创建场景 const scene = new THREE.Scene() scene.background = new THREE.Color(0x222222) // 2. 创建相机(75度视野,匹配窗口宽高比) 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) document.body.appendChild(renderer.domElement)这里有几个关键点:
- 场景是所有物体的容器
- 透视相机模拟人眼视角
- 渲染器将3D场景绘制到2D屏幕上
3.3 添加立方体网格
现在场景还是空的,我们加个立方体:
// 创建立方体几何体 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)Mesh是Three.js的核心概念,它结合了几何体(形状)和材质(外观)。
4. 实现动画循环
4.1 基本动画原理
3D动画的本质就是不断更新物体属性并重绘。Three.js使用requestAnimationFrame实现流畅动画:
function animate() { requestAnimationFrame(animate) // 旋转立方体 cube.rotation.x += 0.01 cube.rotation.y += 0.01 // 渲染场景 renderer.render(scene, camera) } animate()这个循环会以显示器刷新率(通常60FPS)运行,保证动画流畅。
4.2 处理窗口大小变化
当浏览器窗口调整大小时,我们需要更新相机和渲染器:
window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) })如果不做这个处理,画面会变形,影响视觉效果。
5. 增强场景效果
5.1 添加光源
之前的立方体看起来是平的,因为没有光影。我们添加点光源:
const light = new THREE.PointLight(0xffffff, 1, 100) light.position.set(5, 5, 5) scene.add(light) // 改用受光影响的材质 const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 })现在立方体有了明暗变化,看起来更立体了。
5.2 显示坐标轴辅助
调试时显示坐标轴很有帮助:
const axesHelper = new THREE.AxesHelper(5) scene.add(axesHelper)红色=X轴,绿色=Y轴,蓝色=Z轴。
5.3 添加轨道控制器
让用户可以用鼠标旋转场景:
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' const controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true记得在动画循环中更新控制器:
function animate() { requestAnimationFrame(animate) controls.update() renderer.render(scene, camera) }6. 完整代码与优化建议
6.1 完整示例代码
import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' // 初始化场景、相机、渲染器 const scene = new THREE.Scene() scene.background = new THREE.Color(0x222222) const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) camera.position.z = 5 const renderer = new THREE.WebGLRenderer({ antialias: true }) renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement) // 添加立方体 const geometry = new THREE.BoxGeometry(1, 1, 1) const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 }) const cube = new THREE.Mesh(geometry, material) scene.add(cube) // 添加光源 const light = new THREE.PointLight(0xffffff, 1, 100) light.position.set(5, 5, 5) scene.add(light) // 辅助工具 const axesHelper = new THREE.AxesHelper(5) scene.add(axesHelper) const controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true // 处理窗口大小变化 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) }) // 动画循环 function animate() { requestAnimationFrame(animate) cube.rotation.x += 0.01 cube.rotation.y += 0.01 controls.update() renderer.render(scene, camera) } animate()6.2 性能优化建议
- 重用几何体和材质:相同物体使用相同实例
- 合理使用灯光:每个灯光都会增加计算量
- 使用性能监控:添加stats.js显示帧率
- 按需渲染:静态场景可以不用每帧渲染
7. 调试技巧与常见问题
7.1 实用调试方法
- 场景导出:用
scene.toJSON()导出场景配置 - 控制台调试:直接访问THREE对象检查属性
- GUI调节:用dat.GUI创建参数控制面板
7.2 常见错误解决
- 黑屏问题:检查相机位置和物体位置
- 材质不显示:确认是否正确添加了光源
- 性能卡顿:减少多边形数量或使用LOD
8. 项目结构与扩展
8.1 推荐项目结构
threejs-project/ ├── public/ # 静态资源 ├── src/ │ ├── assets/ # 模型纹理 │ ├── components/ # 可复用组件 │ ├── scenes/ # 场景配置 │ └── main.js # 入口文件 ├── package.json └── index.html8.2 学习资源推荐
- 官方文档:Three.js官网示例
- 在线编辑器:Three.js官方编辑器
- 社区论坛:Stack Overflow的Three.js标签