Three.js 简介与安装
Three.js 简介
Three.js 是一个基于 WebGL 的 JavaScript 3D 库,由 Ricardo Cabello(Mr.doob)于 2010 年创建并开源。它将 WebGL 的底层 API 封装成更易使用的高级接口,让开发者能够在网页上轻松创建和展示 3D 内容。
什么是 WebGL?
WebGL(Web Graphics Library)是一种在浏览器中无需插件即可渲染 3D 图形的 JavaScript API。它基于 OpenGL ES 2.0,允许在 HTML5 <canvas> 元素中使用 GPU 加速渲染。
WebGL 的优势:
- 硬件加速:直接使用 GPU 进行图形渲染,性能强劲
- 跨平台:支持所有现代浏览器,无需安装插件
- 开放标准:由 Khronos Group 维护,是一个开放的标准
WebGL 的挑战:
- 学习曲线陡峭:需要了解图形学、着色器编程等专业知识
- 代码量大:即使是简单的场景也需要大量样板代码
- 调试困难:底层 API 错误处理复杂
Three.js 的出现就是为了解决这些问题。
Three.js 的优势
1. 降低学习门槛
// WebGL 原生代码(简化版)
const canvas = document.getElementById('canvas')
const gl = canvas.getContext('webgl')
// 编写顶点着色器
const vertexShaderSource = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`
// 编写片元着色器
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0.5, 1);
}
`
// 创建着色器程序...(需要几十行代码)// Three.js 代码
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, width / height)
const renderer = new THREE.WebGLRenderer()
renderer.render(scene, camera)2. 丰富的功能
- 几何体:内置多种几何体(立方体、球体、圆柱体等)
- 材质:多种材质类型(基础材质、PBR 材质、着色器材质等)
- 光照:支持多种光源类型和实时阴影
- 动画:关键帧动画、骨骼动画、变形动画
- 模型加载:支持 GLTF、OBJ、FBX 等格式
- 后处理:景深、辉光、抗锯齿等后期效果
- 交互:射线拾取、控制器等
3. 活跃的社区
- GitHub Stars:超过 90k+
- 贡献者:1000+ 开发者
- 文档完善:官方文档、示例丰富
- 社区活跃:论坛、Discord、Stack Overflow 都有活跃讨论
Three.js 能做什么?
电商产品展示
- 3D 产品旋转展示
- 产品配置器(颜色、材质选择)
- 虚拟试穿、试戴
- 360° 全景展示
游戏开发
- 休闲网页游戏
- 3D 小游戏
- 游戏场景与角色展示
- 游戏原型开发
数据可视化
- 3D 图表(柱状图、饼图等)
- 地理信息系统(GIS)
- 科学数据可视化
- 实时数据监控
建筑与设计
- 建筑模型展示
- 室内设计预览
- VR 看房
- 城市规划展示
教育培训
- 3D 教学模型
- 虚拟实验室
- 交互式学习内容
- 医学解剖模型
艺术与创意
- 数字艺术作品
- 交互式装置
- 创意网站
- 音乐可视化
Three.js 架构
核心组件
Three.js 的核心架构包含以下主要组件:
Scene(场景)
├── Object3D(3D 对象)
│ ├── Mesh(网格)= Geometry + Material
│ ├── Light(光源)
│ ├── Camera(相机)
│ └── Group(组)
└── ...1. Scene(场景)
场景是所有 3D 对象的容器,类似于现实世界的"舞台"。
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xffffff) // 设置背景色2. Camera(相机)
相机决定了观察者看场景的视角。Three.js 提供多种相机类型:
相机类型对比:
| 相机类型 | 说明 | 应用场景 |
|---|---|---|
PerspectiveCamera | 透视相机,模拟人眼视角 | 大多数3D场景 |
OrthographicCamera | 正交相机,无透视效果 | CAD、2.5D游戏 |
CubeCamera | 立方体相机,6个方向 | 环境映射、反射 |
StereoCamera | 立体相机,双视角 | VR/AR应用 |
PerspectiveCamera 参数详解:
const camera = new THREE.PerspectiveCamera(
75, // fov: 视野角度(Field of View),0-180度
window.innerWidth / window.innerHeight, // aspect: 宽高比
0.1, // near: 近裁剪面,距离相机多近开始渲染
1000 // far: 远裁剪面,距离相机多远停止渲染
)
camera.position.set(0, 0, 5) // 设置相机位置
// 参数说明:
// - fov: 值越大,视野越广(类似广角镜头);值越小,视野越窄(类似长焦镜头)
// - aspect: 必须与画布宽高比一致,否则图像会变形
// - near/far: 不在此范围内的对象不会被渲染,合理设置可优化性能OrthographicCamera 正交相机:
const aspect = window.innerWidth / window.innerHeight
const frustumSize = 5 // 视锥体大小
const camera = new THREE.OrthographicCamera(
frustumSize * aspect / -2, // left
frustumSize * aspect / 2, // right
frustumSize / 2, // top
frustumSize / -2, // bottom
0.1, // near
1000 // far
)相机常用方法:
| 方法 | 说明 | 示例 |
|---|---|---|
lookAt(x, y, z) | 设置相机朝向 | camera.lookAt(0, 0, 0) |
updateProjectionMatrix() | 更新投影矩阵 | camera.updateProjectionMatrix() |
getWorldDirection() | 获取相机方向 | camera.getWorldDirection() |
updateWorldMatrix() | 更新世界矩阵 | camera.updateWorldMatrix() |
3. Renderer(渲染器)
渲染器负责将场景绘制到屏幕上。Three.js 提供多种渲染器,WebGLRenderer 是最常用的。
渲染器类型对比:
| 渲染器 | 说明 | 性能 | 兼容性 |
|---|---|---|---|
WebGLRenderer | WebGL 渲染器 | 高 | 现代浏览器 |
WebGL1Renderer | WebGL 1.0 渲染器 | 中 | 兼容性更好 |
WebGPURenderer | WebGPU 渲染器 | 最高 | 新特性,有限支持 |
WebGLRenderer 配置参数详解:
const renderer = new THREE.WebGLRenderer({
// 基础配置
canvas: undefined, // 指定 canvas 元素,默认自动创建
context: undefined, // 指定 WebGL 上下文
alpha: false, // 是否支持透明背景
premultipliedAlpha: true, // 是否预乘 alpha 值
antialias: false, // 是否开启抗锯齿
stencil: true, // 是否使用模板缓冲区
// 性能配置
powerPreference: 'default', // GPU 电源管理: 'default' | 'high-performance' | 'low-power'
precision: 'highp', // 着色器精度: 'highp' | 'mediump' | 'lowp'
// 高级配置
logarithmicDepthBuffer: false, // 对数深度缓冲区(大场景优化)
preserveDrawingBuffer: false, // 保留绘图缓冲区(截图需要)
// 后处理相关
depth: true, // 深度缓冲区
failIfMajorPerformanceCaveat: false // 性能警告检测
})
// 常用配置方法
renderer.setSize(width, height) // 设置渲染尺寸
renderer.setPixelRatio(window.devicePixelRatio) // 设置像素比(高清屏适配)
renderer.setClearColor(0x000000, 1) // 设置背景色
renderer.setClearAlpha(0) // 设置背景透明度
renderer.setScissor(x, y, width, height) // 设置裁剪区域
renderer.setViewport(x, y, width, height) // 设置视口
// 阴影配置
renderer.shadowMap.enabled = true // 开启阴影
renderer.shadowMap.type = THREE.PCFSoftShadowMap // 阴影类型
// 色彩管理
renderer.outputColorSpace = THREE.SRGBColorSpace // 输出色彩空间
renderer.toneMapping = THREE.ACESFilmicToneMapping // 色调映射
renderer.toneMappingExposure = 1.0 // 曝光度
document.body.appendChild(renderer.domElement)常用方法:
| 方法 | 说明 | 示例 |
|---|---|---|
render(scene, camera) | 渲染场景 | renderer.render(scene, camera) |
clear() | 清除缓冲区 | renderer.clear() |
dispose() | 释放资源 | renderer.dispose() |
forceContextLoss() | 强制丢失上下文 | renderer.forceContextLoss() |
4. Mesh(网格)
网格是场景中可见的 3D 对象,由几何体和材质组成。
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)5. Light(光源)
光源为场景提供照明,影响材质的渲染效果。
const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(5, 5, 5)
scene.add(light)渲染流程
Three.js 的渲染流程遵循以下步骤:
初始化阶段:
1. 创建场景
2. 创建相机
3. 创建渲染器
4. 创建几何体和材质
5. 创建网格并添加到场景
6. 创建光源
渲染循环:
1. 更新场景中的对象(位置、旋转等)
2. 渲染器调用 render() 方法
3. 将 3D 场景投影到 2D 画布
4. 显示在屏幕上核心功能模块
Three.js 提供了丰富的功能模块,以下是最常用的核心模块概览:
几何体模块(Geometries)
| 几何体类型 | 说明 | 主要参数 |
|---|---|---|
BoxGeometry | 立方体 | width, height, depth |
SphereGeometry | 球体 | radius, widthSegments, heightSegments |
CylinderGeometry | 圆柱体 | radiusTop, radiusBottom, height |
PlaneGeometry | 平面 | width, height |
TorusGeometry | 圆环 | radius, tube, radialSegments |
ConeGeometry | 圆锥 | radius, height, radialSegments |
// 创建不同几何体示例
const box = new THREE.BoxGeometry(1, 1, 1)
const sphere = new THREE.SphereGeometry(0.5, 32, 32)
const cylinder = new THREE.CylinderGeometry(0.5, 0.5, 2, 32)材质模块(Materials)
| 材质类型 | 说明 | 是否受光照影响 |
|---|---|---|
MeshBasicMaterial | 基础材质,不受光照影响 | 否 |
MeshStandardMaterial | PBR 标准材质 | 是 |
MeshPhongMaterial | Phong 光照材质 | 是 |
MeshLambertMaterial | Lambert 光照材质 | 是 |
MeshNormalMaterial | 法线材质(调试用) | 否 |
ShaderMaterial | 自定义着色器材质 | 可选 |
// 材质创建示例
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const standardMaterial = new THREE.MeshStandardMaterial({
color: 0x00ff00,
metalness: 0.5, // 金属度 (0-1)
roughness: 0.5 // 粗糙度 (0-1)
})光源模块(Lights)
| 光源类型 | 说明 | 性能消耗 |
|---|---|---|
AmbientLight | 环境光,均匀照亮场景 | 低 |
DirectionalLight | 平行光,模拟太阳光 | 中 |
PointLight | 点光源,向所有方向发散 | 中 |
SpotLight | 聚光灯,锥形光束 | 高 |
HemisphereLight | 半球光,天空和地面两种颜色 | 低 |
// 光源创建示例
const ambientLight = new THREE.AmbientLight(0x404040, 0.5)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
directionalLight.position.set(5, 5, 5)
directionalLight.castShadow = true // 开启阴影加载器模块(Loaders)
Three.js 提供了多种资源加载器:
| 加载器 | 支持格式 | 说明 |
|---|---|---|
GLTFLoader | .gltf, .glb | 推荐,支持动画、材质、骨骼 |
OBJLoader | .obj | 通用3D格式 |
FBXLoader | .fbx | 支持动画 |
STLLoader | .stl | 3D打印格式 |
TextureLoader | jpg, png, gif | 纹理图片加载 |
// 加载模型示例
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
const loader = new GLTFLoader()
loader.load(
'model.glb',
(gltf) => {
scene.add(gltf.scene)
},
(progress) => {
console.log('Loading:', (progress.loaded / progress.total * 100) + '%')
},
(error) => {
console.error('Error:', error)
}
)控制器模块(Controls)
| 控制器 | 说明 | 主要用途 |
|---|---|---|
OrbitControls | 轨道控制器 | 鼠标旋转、缩放、平移 |
FlyControls | 飞行控制器 | 第一人称飞行 |
FirstPersonControls | 第一人称控制器 | 类似FPS游戏 |
TrackballControls | 轨迹球控制器 | 自由旋转视角 |
// OrbitControls 使用示例
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true // 开启阻尼效果
controls.dampingFactor = 0.05 // 阻尼系数
controls.minDistance = 1 // 最小缩放距离
controls.maxDistance = 100 // 最大缩放距离
controls.maxPolarAngle = Math.PI / 2 // 限制垂直旋转角度安装方式
Three.js 提供多种安装方式,你可以根据项目需求选择合适的方式。
1. NPM 安装(推荐)
适用于现代前端项目,支持模块化打包。
安装
npm install three使用
// 方式一:全局导入
import * as THREE from 'three'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, width / height)
const renderer = new THREE.WebGLRenderer()
// 方式二:按需导入(推荐)
import { Scene, PerspectiveCamera, WebGLRenderer } from 'three'
const scene = new Scene()
const camera = new PerspectiveCamera(75, width / height)
const renderer = new WebGLRenderer()导入示例和插件
// 导入 OrbitControls 控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 导入 GLTFLoader 加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// 导入后处理效果
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'TypeScript 支持
Three.js 自带 TypeScript 类型定义,无需额外安装。
import * as THREE from 'three'
const scene: THREE.Scene = new THREE.Scene()
const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(
75,
width / height
)2. CDN 引入
适用于快速原型开发或简单项目。
使用最新版本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js CDN</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<script>
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// ...其他代码
</script>
</body>
</html>使用特定版本
<!-- 指定版本号 -->
<script src="https://cdn.jsdelivr.net/npm/three@0.150.0/build/three.min.js"></script>
<!-- 或者使用 unpkg -->
<script src="https://unpkg.com/three@0.150.0/build/three.min.js"></script>
<!-- 或者使用 cdnjs -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r150/three.min.js"></script>CDN 导入模块
<!-- 主文件 -->
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<!-- OrbitControls -->
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
<!-- GLTFLoader -->
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/loaders/GLTFLoader.js"></script>
<script>
// 使用
const controls = new THREE.OrbitControls(camera, renderer.domElement)
const loader = new THREE.GLTFLoader()
</script>3. 直接下载
适用于离线开发或需要修改源码的场景。
下载方式
-
GitHub Releases
访问 Three.js Releases,下载最新版本的源码。
-
克隆仓库
bashgit clone https://github.com/mrdoob/three.js.git
使用本地文件
<script src="./path/to/three.js"></script>
<!-- 或使用压缩版 -->
<script src="./path/to/three.min.js"></script>4. 在线编辑器
适用于学习和快速测试。
- Three.js Editor: https://threejs.org/editor/
- CodeSandbox: https://codesandbox.io/
- StackBlitz: https://stackblitz.com/
版本选择
版本命名规则
Three.js 遵循语义化版本控制:
- 主版本号:重大更新,可能包含不兼容的 API 变更
- 次版本号:新功能添加,向后兼容
- 修订号:Bug 修复,向后兼容
例如:r150 表示第 150 个版本
如何选择版本?
开发环境
# 使用最新稳定版
npm install three
# 使用特定版本
npm install three@0.150.0
# 使用最新开发版
npm install three@latest生产环境
# 锁定版本号
npm install three@0.150.0
# 或在 package.json 中锁定
{
"dependencies": {
"three": "0.150.0"
}
}版本迁移
Three.js 版本更新较快,迁移时需要注意:
- 查看更新日志: https://github.com/mrdoob/three.js/releases
- 关注废弃 API: 查看控制台的废弃警告
- 测试兼容性: 升级后全面测试项目
浏览器支持
支持的浏览器
Three.js 支持所有支持 WebGL 的现代浏览器:
| 浏览器 | 最低版本 | 推荐版本 |
|---|---|---|
| Chrome | 9+ | 最新版 |
| Firefox | 4+ | 最新版 |
| Safari | 5.1+ | 最新版 |
| Edge | 12+ | 最新版 |
| Opera | 12+ | 最新版 |
移动端支持
- iOS Safari 8+
- Android Chrome 60+
- Android Firefox 60+
WebGL 支持检测
// 检测 WebGL 支持
function isWebGLAvailable() {
try {
const canvas = document.createElement('canvas')
return !!(
window.WebGLRenderingContext &&
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
)
} catch (e) {
return false
}
}
if (!isWebGLAvailable()) {
alert('您的浏览器不支持 WebGL,请升级浏览器')
}或者使用 Three.js 提供的检测工具:
import { WEBGL } from 'three/examples/jsm/WebGL.js'
if (WEBGL.isWebGLAvailable()) {
// WebGL 支持
} else {
const warning = WEBGL.getWebGLErrorMessage()
document.body.appendChild(warning)
}项目依赖
核心依赖
Three.js 本身没有外部依赖,是一个独立的库。
开发依赖(推荐)
{
"devDependencies": {
"vite": "^4.0.0", // 构建工具
"typescript": "^5.0.0", // TypeScript 支持
"@types/three": "^0.150.0" // Three.js 类型定义
}
}可选依赖
{
"dependencies": {
// 物理引擎
"cannon-es": "^0.20.0",
"ammo.js": "^0.0.10",
// 动画库
"gsap": "^3.12.0",
// 工具库
"lodash": "^4.17.21"
}
}最佳实践
1. 使用模块化导入
// ❌ 不推荐:全局导入
import * as THREE from 'three'
// ✅ 推荐:按需导入
import { Scene, PerspectiveCamera, WebGLRenderer } from 'three'2. 锁定版本号
{
"dependencies": {
"three": "0.150.0" // 锁定具体版本
}
}3. 使用构建工具
推荐使用 Vite、Webpack 等现代构建工具:
// vite.config.js
export default {
optimizeDeps: {
include: ['three']
}
}4. 按需加载插件
// ✅ 推荐:按需导入插件
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// ❌ 不推荐:全量导入
import 'three/examples/js/controls/OrbitControls'5. 资源释放
避免内存泄漏,及时释放不再使用的资源:
// 释放几何体
geometry.dispose()
// 释放材质
material.dispose()
// 释放纹理
texture.dispose()
// 释放渲染器
renderer.dispose()
// 从场景移除对象
scene.remove(mesh)6. 性能优化建议
// 限制像素比,避免高清屏性能问题
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
// 使用 requestAnimationFrame 控制渲染循环
function animate() {
requestAnimationFrame(animate)
renderer.render(scene, camera)
}
// 合并几何体减少 draw calls
const mergedGeometry = BufferGeometryUtils.mergeGeometries(geometries)
// 使用 InstancedMesh 渲染大量相同对象
const instancedMesh = new THREE.InstancedMesh(geometry, material, count)
// 按需渲染(非动画场景)
let needsUpdate = true
function render() {
if (needsUpdate) {
renderer.render(scene, camera)
needsUpdate = false
}
}API 接口参考
Scene(场景)
| 属性/方法 | 类型 | 说明 |
|---|---|---|
background | Color/Texture | 场景背景色或背景贴图 |
environment | Texture | 环境贴图(影响材质反射) |
fog | Fog | 场景雾效果 |
children | Array | 场景中所有子对象 |
add(object) | Method | 添加对象到场景 |
remove(object) | Method | 从场景移除对象 |
traverse(callback) | Method | 遍历场景树 |
Object3D(3D对象基类)
| 属性/方法 | 类型 | 说明 |
|---|---|---|
position | Vector3 | 对象位置 (x, y, z) |
rotation | Euler | 对象旋转(欧拉角) |
scale | Vector3 | 对象缩放 |
visible | Boolean | 是否可见 |
castShadow | Boolean | 是否投射阴影 |
receiveShadow | Boolean | 是否接收阴影 |
userData | Object | 自定义数据 |
translateX/Y/Z(distance) | Method | 沿轴移动 |
rotateX/Y/Z(angle) | Method | 绕轴旋转 |
lookAt(target) | Method | 朝向目标 |
Mesh(网格)
const mesh = new THREE.Mesh(geometry, material)
// 常用属性
mesh.position.set(0, 0, 0) // 位置
mesh.rotation.set(0, 0, 0) // 旋转
mesh.scale.set(1, 1, 1) // 缩放
mesh.visible = true // 可见性
mesh.castShadow = true // 投射阴影
mesh.receiveShadow = true // 接收阴影BufferGeometry(缓冲几何体)
| 属性/方法 | 说明 |
|---|---|
attributes.position | 顶点位置数据 |
attributes.normal | 顶点法线数据 |
attributes.uv | UV 坐标数据 |
attributes.color | 顶点颜色数据 |
index | 索引数据 |
boundingBox | 包围盒(需调用 computeBoundingBox) |
boundingSphere | 包围球(需调用 computeBoundingSphere) |
computeVertexNormals() | 计算顶点法线 |
dispose() | 释放资源 |
Material(材质基类)
| 属性 | 类型 | 说明 |
|---|---|---|
color | Color | 材质颜色 |
opacity | Number | 透明度 (0-1) |
transparent | Boolean | 是否透明 |
visible | Boolean | 是否可见 |
side | Constant | 渲染面:FrontSide/BackSide/DoubleSide |
wireframe | Boolean | 线框模式 |
map | Texture | 颜色贴图 |
normalMap | Texture | 法线贴图 |
aoMap | Texture | 环境遮蔽贴图 |
Texture(纹理)
const texture = new THREE.TextureLoader().load('texture.jpg')
// 常用属性
texture.wrapS = THREE.RepeatWrapping // 水平重复
texture.wrapT = THREE.RepeatWrapping // 垂直重复
texture.repeat.set(2, 2) // 重复次数
texture.offset.set(0.5, 0.5) // 偏移
texture.rotation = Math.PI / 4 // 旋转
texture.center.set(0.5, 0.5) // 旋转中心
texture.encoding = THREE.sRGBEncoding // 编码方式
// 纹理过滤
texture.minFilter = THREE.LinearMipmapLinearFilter // 缩小过滤
texture.magFilter = THREE.LinearFilter // 放大过滤常见问题
Q1: NPM 安装和 CDN 引入有什么区别?
A:
- NPM 安装:适合现代前端项目,支持模块化、Tree-shaking、TypeScript,打包后体积更小
- CDN 引入:适合快速原型开发,无需构建工具,但无法按需加载
Q2: 如何选择 Three.js 版本?
A:
- 学习阶段:使用最新版本,体验最新特性
- 生产环境:使用稳定版本,锁定版本号
- 长期项目:定期更新,关注更新日志
Q3: Three.js 需要什么基础?
A:
- 必需:JavaScript 基础、HTML/CSS
- 推荐:ES6+ 语法、模块化开发
- 进阶:WebGL 基础、图形学概念、GLSL 着色器
Q4: 如何调试 Three.js 应用?
A:
- 使用浏览器开发者工具
- 安装 Three.js DevTools 扩展
- 使用
console.log查看对象属性 - 使用 Stats.js 监控性能
Q5: Three.js 支持哪些 3D 模型格式?
A:
- 推荐: GLTF/GLB(官方推荐格式)
- 支持: OBJ、FBX、STL、Collada、3DS 等
- 详见: 模型加载 章节
Q6: 如何解决场景黑屏问题?
A: 场景黑屏常见原因及解决方案:
// 1. 检查相机位置
console.log(camera.position)
// 2. 确保对象在视锥体内
const box = new THREE.Box3().setFromObject(mesh)
console.log(box) // 查看包围盒
// 3. 检查材质是否需要光照
// MeshStandardMaterial 和 MeshPhongMaterial 需要光源
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }) // 不受光照影响
// 4. 确保调用了 render()
renderer.render(scene, camera)
// 5. 检查渲染器尺寸
console.log(renderer.getSize(new THREE.Vector2()))Q7: 如何优化 Three.js 性能?
A:
// 1. 减少几何体面数
const geometry = new THREE.SphereGeometry(1, 16, 16) // 较少分段
// 2. 合并几何体
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils'
const mergedGeometry = BufferGeometryUtils.mergeGeometries([geo1, geo2])
// 3. 使用 InstancedMesh
const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000)
// 4. 限制像素比
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
// 5. 关闭抗锯齿(移动端)
const renderer = new THREE.WebGLRenderer({ antialias: false })
// 6. 使用 LOD(细节层次)
const lod = new THREE.LOD()
lod.addLevel(highPolyMesh, 10)
lod.addLevel(mediumPolyMesh, 20)
lod.addLevel(lowPolyMesh, 30)
// 7. 视锥体剔除(默认开启)
// 确保对象的 frustumCulled 属性为 true
mesh.frustumCulled = trueQ8: 如何处理响应式布局?
A:
// 监听窗口大小变化
window.addEventListener('resize', () => {
const width = window.innerWidth
const height = window.innerHeight
// 更新相机宽高比
camera.aspect = width / height
camera.updateProjectionMatrix()
// 更新渲染器尺寸
renderer.setSize(width, height)
})
// 使用 ResizeObserver 监听容器大小变化(推荐)
const container = document.getElementById('container')
const resizeObserver = new ResizeObserver((entries) => {
const { width, height } = entries[0].contentRect
camera.aspect = width / height
camera.updateProjectionMatrix()
renderer.setSize(width, height)
})
resizeObserver.observe(container)Q9: 如何实现对象动画?
A:
// 方式1:直接修改属性
function animate() {
requestAnimationFrame(animate)
mesh.rotation.y += 0.01
renderer.render(scene, camera)
}
// 方式2:使用三角函数
const clock = new THREE.Clock()
function animate() {
requestAnimationFrame(animate)
const time = clock.getElapsedTime()
mesh.position.y = Math.sin(time) * 2
renderer.render(scene, camera)
}
// 方式3:使用 GSAP 动画库
import gsap from 'gsap'
gsap.to(mesh.position, {
duration: 2,
x: 5,
y: 3,
ease: 'power2.inOut'
})
// 方式4:使用 Three.js 动画系统
import { AnimationMixer } from 'three'
const mixer = new AnimationMixer(model)
const action = mixer.clipAction(animationClip)
action.play()
function animate() {
requestAnimationFrame(animate)
mixer.update(deltaTime)
renderer.render(scene, camera)
}Q10: 如何实现点击选中对象?
A:
import { Raycaster, Vector2 } from 'three'
const raycaster = new Raycaster()
const mouse = new Vector2()
window.addEventListener('click', (event) => {
// 计算鼠标归一化坐标
mouse.x = (event.clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
// 设置射线
raycaster.setFromCamera(mouse, camera)
// 检测相交对象
const intersects = raycaster.intersectObjects(scene.children)
if (intersects.length > 0) {
const selected = intersects[0].object
console.log('选中对象:', selected)
// 高亮显示
selected.material.emissive.setHex(0xff0000)
}
})相关链接
下一步
现在你已经了解了 Three.js 的基本概念和安装方法,接下来可以: