环境搭建
在开始 Three.js 开发之前,我们需要搭建一个合适的开发环境。本章将介绍几种常见的环境配置方式,从最简单的 CDN 引入到现代化的构建工具配置。
浏览器要求
Three.js 依赖 WebGL 进行 3D 渲染,因此需要支持 WebGL 的现代浏览器。主流浏览器的最新版本都支持 WebGL:
- Chrome 9+
- Firefox 4+
- Safari 5.1+
- Edge 12+
- Opera 12+
你可以在浏览器中访问 get.webgl.org 来检测当前浏览器是否支持 WebGL。
方式一:使用 CDN
最简单的方式是通过 CDN 直接引入 Three.js。这种方式适合快速原型开发和学习的初期阶段。
创建一个 HTML 文件,内容如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 示例</title>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@latest/build/three.module.js",
"three/addons/": "https://unpkg.com/three@latest/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);
// 创建相机
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);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// 创建一个立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff88 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 添加光源
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);
// 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
controls.update();
renderer.render(scene, camera);
}
animate();
// 响应窗口大小变化
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>
这个例子使用了 ES Modules 和 importmap。importmap 告诉浏览器如何解析模块导入路径,让我们可以使用简洁的模块名称而不是完整的 URL。
关键点说明:
antialias: true 开启抗锯齿,让边缘更平滑。
setPixelRatio 设置设备像素比,在高分辨率屏幕上显示更清晰。
OrbitControls 是一个扩展控件,让用户可以用鼠标旋转、缩放、平移视角。
方式二:使用 npm 和构建工具
对于正式项目,推荐使用 npm 管理依赖,配合 Vite 或 Webpack 等构建工具。
使用 Vite(推荐)
Vite 是一个现代化的前端构建工具,启动速度快,配置简单。
首先确保已安装 Node.js(建议 18+ 版本),然后执行:
# 创建项目
npm create vite@latest threejs-demo -- --template vanilla
# 进入项目目录
cd threejs-demo
# 安装 Three.js
npm install three
# 启动开发服务器
npm run dev
项目创建后,修改 main.js 文件:
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 初始化场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);
// 初始化相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, 0, 5);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
// 轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// 创建物体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
color: 0x00ff88,
metalness: 0.3,
roughness: 0.4
});
const cube = new THREE.Mesh(geometry, material);
cube.castShadow = true;
scene.add(cube);
// 地面
const groundGeometry = new THREE.PlaneGeometry(10, 10);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x333344 });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -1;
ground.receiveShadow = true;
scene.add(ground);
// 光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);
// 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
controls.update();
renderer.render(scene, camera);
}
animate();
// 窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
使用 Webpack
如果你需要在现有的 Webpack 项目中集成 Three.js:
npm install three
webpack 配置通常不需要特殊处理,Three.js 会自动处理模块导入。
方式三:使用 TypeScript
Three.js 提供了完整的 TypeScript 类型定义,在 TypeScript 项目中使用可以获得更好的类型提示和代码补全。
# 创建 Vite + TypeScript 项目
npm create vite@latest threejs-ts-demo -- --template vanilla-ts
cd threejs-ts-demo
npm install three
TypeScript 中的使用方式与 JavaScript 基本相同:
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
class ThreeScene {
private scene: THREE.Scene;
private camera: THREE.PerspectiveCamera;
private renderer: THREE.WebGLRenderer;
private controls: OrbitControls;
private cube: THREE.Mesh;
constructor() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x1a1a2e);
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.z = 5;
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(this.renderer.domElement);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff88 });
this.cube = new THREE.Mesh(geometry, material);
this.scene.add(this.cube);
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
this.scene.add(light);
this.scene.add(new THREE.AmbientLight(0xffffff, 0.5));
this.setupEventListeners();
this.animate();
}
private setupEventListeners(): void {
window.addEventListener('resize', () => {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
});
}
private animate(): void {
requestAnimationFrame(() => this.animate());
this.cube.rotation.x += 0.01;
this.cube.rotation.y += 0.01;
this.controls.update();
this.renderer.render(this.scene, this.camera);
}
}
new ThreeScene();
开发工具推荐
VS Code 扩展
Three.js Snippets:提供 Three.js 代码片段,加快编码速度。
GLSL Lint:如果你编写自定义着色器,这个扩展可以检查 GLSL 语法。
Live Server:在开发时自动刷新页面。
调试工具
Chrome DevTools:浏览器自带的开发者工具,可以检查 WebGL 上下文、性能等。
Three.js Inspector:Chrome 扩展,可以检查场景中的对象层级、属性等。
Spector.js:WebGL 调试工具,可以捕获每一帧的 WebGL 调用。
常见问题
黑屏问题
如果页面显示黑屏,检查以下几点:
- 确认 WebGL 可用
- 检查相机位置是否在物体内部或太远
- 确认场景中有光源(如果使用需要光照的材质)
- 检查控制台是否有错误信息
性能问题
如果渲染卡顿,可以尝试:
- 减少几何体的顶点数量
- 降低渲染器的像素比
- 关闭不必要的阴影
- 使用
requestAnimationFrame而不是setInterval
模块导入问题
如果遇到模块导入错误:
- 确保使用
type="module"或构建工具 - 检查 importmap 配置是否正确
- 确认 Three.js 版本兼容性
下一步
环境搭建完成后,我们就可以开始学习 Three.js 的核心概念了。下一章将详细介绍场景、相机和渲染器这三个最基础也是最重要的组件。