threejs-builder
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseThree.js Builder
Three.js 应用构建指南
A focused skill for creating simple, performant Three.js web applications using modern ES module patterns.
这是一个专注于使用现代ES模块模式创建简洁、高性能Three.js网页应用的技能。
Philosophy: The Scene Graph Mental Model
设计理念:场景图思维模型
Three.js is built on the scene graph—a hierarchical tree of objects where parent transformations affect children. Understanding this mental model is key to effective 3D web development.
Before creating a Three.js app, ask:
- What is the core visual element? (geometry, shape, model)
- What interaction does the user need? (none, orbit controls, custom input)
- What performance constraints exist? (mobile, desktop, WebGL capabilities)
- What animation brings it to life? (rotation, movement, transitions)
Core principles:
- Scene Graph First: Everything added to renders. Use
scenefor hierarchical transforms.Group - Primitives as Building Blocks: Built-in geometries (Box, Sphere, Torus) cover 80% of simple use cases.
- Animation as Transformation: Change position/rotation/scale over time using or
requestAnimationFrame.renderer.setAnimationLoop - Performance Through Simplicity: Fewer objects, fewer draw calls, reusable geometries/materials.
Three.js 基于场景图构建——这是一种对象层级树结构,父对象的变换会影响子对象。理解这一思维模型是高效进行3D网页开发的关键。
在创建Three.js应用前,请思考:
- 核心视觉元素是什么?(几何体、形状、模型)
- 用户需要哪些交互?(无交互、轨道控制、自定义输入)
- 存在哪些性能限制?(移动端、桌面端、WebGL能力)
- 什么样的动画能让内容更生动?(旋转、移动、过渡效果)
核心原则:
- 场景图优先:所有添加到的对象都会被渲染。使用
scene实现层级变换。Group - 基础几何体为构建块:内置几何体(立方体、球体、圆环等)可覆盖80%的简单应用场景。
- 动画即变换:使用或
requestAnimationFrame随时间改变对象的位置/旋转/缩放。renderer.setAnimationLoop - 通过简洁保障性能:减少对象数量、绘制调用,复用几何体和材质。
Quick Start: Essential Setup
快速开始:基础设置
Minimal HTML Template
极简HTML模板
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js App</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { overflow: hidden; background: #000; }
canvas { display: block; }
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
// Your 3D content here
// ...
camera.position.z = 5;
// Animation loop
renderer.setAnimationLoop((time) => {
renderer.render(scene, camera);
});
// Handle resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js App</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { overflow: hidden; background: #000; }
canvas { display: block; }
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
// 场景设置
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
// 在此添加你的3D内容
// ...
camera.position.z = 5;
// 动画循环
renderer.setAnimationLoop((time) => {
renderer.render(scene, camera);
});
// 处理窗口大小变化
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>Geometries
几何体
Built-in primitives cover most simple app needs. Use only for custom shapes.
BufferGeometryCommon primitives:
- - cubes, boxes
BoxGeometry(width, height, depth) - - balls, planets
SphereGeometry(radius, widthSegments, heightSegments) - - tubes, cylinders
CylinderGeometry(radiusTop, radiusBottom, height) - - donuts, rings
TorusGeometry(radius, tube) - - floors, walls, backgrounds
PlaneGeometry(width, height) - - spikes, cones
ConeGeometry(radius, height) - - low-poly spheres (detail=0)
IcosahedronGeometry(radius, detail)
Usage:
javascript
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x44aa88 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);内置基础几何体可满足大多数简单应用的需求。仅在需要自定义形状时使用。
BufferGeometry常用基础几何体:
- - 立方体、长方体
BoxGeometry(width, height, depth) - - 球体、行星模型
SphereGeometry(radius, widthSegments, heightSegments) - - 管道、圆柱体
CylinderGeometry(radiusTop, radiusBottom, height) - - 圆环、甜甜圈形状
TorusGeometry(radius, tube) - - 地面、墙面、背景
PlaneGeometry(width, height) - - 锥体、尖刺形状
ConeGeometry(radius, height) - - 低多边形球体(detail=0时为基础二十面体)
IcosahedronGeometry(radius, detail)
使用示例:
javascript
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x44aa88 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);Materials
材质
Choose material based on lighting needs and visual style.
Material selection guide:
- - No lighting, flat colors. Use for: UI, wireframes, unlit effects
MeshBasicMaterial - - PBR lighting. Default for realistic surfaces
MeshStandardMaterial - - Advanced PBR with clearcoat, transmission. Glass, water
MeshPhysicalMaterial - - Debug, rainbow colors based on normals
MeshNormalMaterial - - Legacy, shininess control. Faster than Standard
MeshPhongMaterial
Common material properties:
javascript
{
color: 0x44aa88, // Hex color
roughness: 0.5, // 0=glossy, 1=matte (Standard/Physical)
metalness: 0.0, // 0=non-metal, 1=metal (Standard/Physical)
emissive: 0x000000, // Self-illumination color
wireframe: false, // Show edges only
transparent: false, // Enable transparency
opacity: 1.0, // 0=invisible, 1=opaque (needs transparent:true)
side: THREE.FrontSide // FrontSide, BackSide, DoubleSide
}根据光照需求和视觉风格选择合适的材质。
材质选择指南:
- - 不受光照影响,纯色填充。适用于:UI元素、线框、无光照效果的场景
MeshBasicMaterial - - PBR光照材质。是实现真实感表面的默认选择
MeshStandardMaterial - - 高级PBR材质,支持清漆、透射效果。适用于玻璃、水面等场景
MeshPhysicalMaterial - - 调试用材质,根据法线方向显示彩虹色
MeshNormalMaterial - - 传统高光材质,可控制光泽度。性能优于Standard材质
MeshPhongMaterial
常用材质属性:
javascript
{
color: 0x44aa88, // 十六进制颜色值
roughness: 0.5, // 粗糙度:0=高光,1=哑光(仅Standard/Physical材质支持)
metalness: 0.0, // 金属度:0=非金属,1=金属(仅Standard/Physical材质支持)
emissive: 0x000000, // 自发光颜色
wireframe: false, // 是否显示线框
transparent: false, // 是否启用透明效果
opacity: 1.0, // 透明度:0=完全透明,1=完全不透明(需配合transparent:true使用)
side: THREE.FrontSide // 渲染面:FrontSide(正面)、BackSide(背面)、DoubleSide(双面)
}Lighting
光照
No light = black screen (except BasicMaterial/NormalMaterial).
Light types:
- - Base illumination everywhere. Use 0.3-0.5
AmbientLight(intensity) - - Sun-like, parallel rays. Cast shadows
DirectionalLight(color, intensity) - - Light bulb, emits in all directions
PointLight(color, intensity, distance) - - Flashlight, cone of light
SpotLight(color, intensity, angle, penumbra)
Typical lighting setup:
javascript
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const mainLight = new THREE.DirectionalLight(0xffffff, 1);
mainLight.position.set(5, 10, 7);
scene.add(mainLight);
const fillLight = new THREE.DirectionalLight(0x88ccff, 0.5);
fillLight.position.set(-5, 0, -5);
scene.add(fillLight);Shadows (advanced, use when needed):
javascript
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
mainLight.castShadow = true;
mainLight.shadow.mapSize.width = 2048;
mainLight.shadow.mapSize.height = 2048;
mesh.castShadow = true;
mesh.receiveShadow = true;若无光照,屏幕将全黑(MeshBasicMaterial和MeshNormalMaterial除外)。
光照类型:
- - 环境光,均匀照亮整个场景。建议强度设置为0.3-0.5
AmbientLight(intensity) - - 平行光,类似太阳光。可投射阴影
DirectionalLight(color, intensity) - - 点光源,向所有方向发射光线,类似灯泡
PointLight(color, intensity, distance) - - 聚光灯,发射锥形光线,类似手电筒
SpotLight(color, intensity, angle, penumbra)
典型光照设置示例:
javascript
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const mainLight = new THREE.DirectionalLight(0xffffff, 1);
mainLight.position.set(5, 10, 7);
scene.add(mainLight);
const fillLight = new THREE.DirectionalLight(0x88ccff, 0.5);
fillLight.position.set(-5, 0, -5);
scene.add(fillLight);阴影效果(高级功能,按需使用):
javascript
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
mainLight.castShadow = true;
mainLight.shadow.mapSize.width = 2048;
mainLight.shadow.mapSize.height = 2048;
mesh.castShadow = true;
mesh.receiveShadow = true;Animation
动画
Transform objects over time using the animation loop.
Animation patterns:
- Continuous rotation:
javascript
renderer.setAnimationLoop((time) => {
mesh.rotation.x = time * 0.001;
mesh.rotation.y = time * 0.0005;
renderer.render(scene, camera);
});- Wave/bobbing motion:
javascript
renderer.setAnimationLoop((time) => {
mesh.position.y = Math.sin(time * 0.002) * 0.5;
renderer.render(scene, camera);
});- Mouse interaction:
javascript
const mouse = new THREE.Vector2();
window.addEventListener('mousemove', (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
renderer.setAnimationLoop(() => {
mesh.rotation.x = mouse.y * 0.5;
mesh.rotation.y = mouse.x * 0.5;
renderer.render(scene, camera);
});通过动画循环实现对象的变换效果。
动画模式示例:
- 持续旋转:
javascript
renderer.setAnimationLoop((time) => {
mesh.rotation.x = time * 0.001;
mesh.rotation.y = time * 0.0005;
renderer.render(scene, camera);
});- 波浪/上下浮动效果:
javascript
renderer.setAnimationLoop((time) => {
mesh.position.y = Math.sin(time * 0.002) * 0.5;
renderer.render(scene, camera);
});- 鼠标交互:
javascript
const mouse = new THREE.Vector2();
window.addEventListener('mousemove', (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
renderer.setAnimationLoop(() => {
mesh.rotation.x = mouse.y * 0.5;
mesh.rotation.y = mouse.x * 0.5;
renderer.render(scene, camera);
});Camera Controls
相机控制
Import OrbitControls from examples for interactive camera movement:
html
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js';
// ... scene setup ...
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
renderer.setAnimationLoop(() => {
controls.update();
renderer.render(scene, camera);
});
</script>从示例库中导入OrbitControls实现交互式相机移动:
html
<script type="module">
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js';
// ... 场景设置代码 ...
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
renderer.setAnimationLoop(() => {
controls.update();
renderer.render(scene, camera);
});
</script>Common Scene Patterns
常见场景模式
Rotating Cube (Hello World)
旋转立方体(入门示例)
javascript
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);
renderer.setAnimationLoop((time) => {
cube.rotation.x = time * 0.001;
cube.rotation.y = time * 0.001;
renderer.render(scene, camera);
});javascript
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);
renderer.setAnimationLoop((time) => {
cube.rotation.x = time * 0.001;
cube.rotation.y = time * 0.001;
renderer.render(scene, camera);
});Floating Particle Field
浮动粒子场
javascript
const particleCount = 1000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount * 3; i += 3) {
positions[i] = (Math.random() - 0.5) * 50;
positions[i + 1] = (Math.random() - 0.5) * 50;
positions[i + 2] = (Math.random() - 0.5) * 50;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const particles = new THREE.Points(geometry, material);
scene.add(particles);javascript
const particleCount = 1000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount * 3; i += 3) {
positions[i] = (Math.random() - 0.5) * 50;
positions[i + 1] = (Math.random() - 0.5) * 50;
positions[i + 2] = (Math.random() - 0.5) * 50;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const particles = new THREE.Points(geometry, material);
scene.add(particles);Animated Background with Foreground Object
带动画背景的前景对象
javascript
// Background grid
const gridHelper = new THREE.GridHelper(50, 50, 0x444444, 0x222222);
scene.add(gridHelper);
// Foreground object
const mainGeometry = new THREE.IcosahedronGeometry(1, 0);
const mainMaterial = new THREE.MeshStandardMaterial({
color: 0xff6600,
flatShading: true
});
const mainMesh = new THREE.Mesh(mainGeometry, mainMaterial);
scene.add(mainMesh);javascript
// 背景网格
const gridHelper = new THREE.GridHelper(50, 50, 0x444444, 0x222222);
scene.add(gridHelper);
// 前景对象
const mainGeometry = new THREE.IcosahedronGeometry(1, 0);
const mainMaterial = new THREE.MeshStandardMaterial({
color: 0xff6600,
flatShading: true
});
const mainMesh = new THREE.Mesh(mainGeometry, mainMaterial);
scene.add(mainMesh);Colors
颜色
Three.js uses hexadecimal color format:
0xRRGGBBCommon hex colors:
- Black: , White:
0x0000000xffffff - Red: , Green:
0xff0000, Blue:0x00ff000x0000ff - Cyan: , Magenta:
0x00ffff, Yellow:0xff00ff0xffff00 - Orange: , Purple:
0xff8800, Pink:0x8800ff0xff0088
Three.js 使用十六进制颜色格式:
0xRRGGBB常用十六进制颜色:
- 黑色:,白色:
0x0000000xffffff - 红色:,绿色:
0xff0000,蓝色:0x00ff000x0000ff - 青色:,品红色:
0x00ffff,黄色:0xff00ff0xffff00 - 橙色:,紫色:
0xff8800,粉色:0x8800ff0xff0088
Anti-Patterns to Avoid
需避免的反模式
Basic Setup Mistakes
基础设置错误
❌ Not importing OrbitControls from correct path
Why bad: Controls won't load, is undefined in modern Three.js
Better: Use or unpkg examples/jsm path
THREE.OrbitControlsimport { OrbitControls } from 'three/addons/controls/OrbitControls.js'❌ Forgetting to add object to scene
Why bad: Object won't render, silent failure
Better: Always call after creating meshes/lights
scene.add(object)❌ Using old pattern instead of
Why bad: More verbose, doesn't handle XR/WebXR automatically
Better:
requestAnimationFramesetAnimationLooprenderer.setAnimationLoop((time) => { ... })❌ 从错误路径导入OrbitControls
问题:控件无法加载,现代Three.js中未定义
解决方法:使用或unpkg的examples/jsm路径
THREE.OrbitControlsimport { OrbitControls } from 'three/addons/controls/OrbitControls.js'❌ 忘记将对象添加到场景
问题:对象不会渲染,无报错信息
解决方法:创建网格/灯光后务必调用
scene.add(object)❌ 使用旧版模式而非
问题:代码更繁琐,无法自动处理XR/WebXR场景
解决方法:使用
requestAnimationFramesetAnimationLooprenderer.setAnimationLoop((time) => { ... })Performance Issues
性能问题
❌ Creating new geometries in animation loop
Why bad: Massive memory allocation, frame rate collapse
Better: Create geometry once, reuse it. Transform only position/rotation/scale
❌ Using too many segments on primitives
Why bad: Unnecessary vertices, GPU overhead
Better: Default segments are usually fine. not
SphereGeometry(1, 32, 16)SphereGeometry(1, 128, 64)❌ Not setting pixelRatio cap
Why bad: 4K/5K displays run at full resolution, poor performance
Better:
Math.min(window.devicePixelRatio, 2)❌ 在动画循环中创建新几何体
问题:大量内存分配,导致帧率骤降
解决方法:仅创建一次几何体,复用它。仅变换位置/旋转/缩放
❌ 给基础几何体设置过多分段数
问题:产生不必要的顶点,增加GPU负载
解决方法:默认分段数通常足够。例如使用而非
SphereGeometry(1, 32, 16)SphereGeometry(1, 128, 64)❌ 未限制pixelRatio值
问题:4K/5K显示器会以全分辨率运行,性能不佳
解决方法:使用
Math.min(window.devicePixelRatio, 2)Code Organization
代码组织问题
❌ Everything in one giant function
Why bad: Hard to modify, hard to debug
Better: Separate setup into functions: , ,
createScene()createLights()createMeshes()❌ Hardcoding all values
Why bad: Difficult to tweak and experiment
Better: Define constants at top:
const CONFIG = { color: 0x00ff88, speed: 0.001 }❌ 所有代码都写在一个大函数中
问题:难以修改和调试
解决方法:将设置代码拆分为多个函数:、、
createScene()createLights()createMeshes()❌ 硬编码所有参数值
问题:难以调整和实验
解决方法:在顶部定义常量:
const CONFIG = { color: 0x00ff88, speed: 0.001 }Variation Guidance
变体设计指导
IMPORTANT: Each Three.js app should feel unique and context-appropriate.
Vary by scenario:
- Portfolio/showcase: Elegant, smooth animations, muted colors
- Game/interactive: Bright colors, snappy controls, particle effects
- Data visualization: Clean lines, grid helpers, clear labels
- Background effect: Subtle, slow movement, dark/gradient backgrounds
- Product viewer: Realistic lighting, PBR materials, smooth orbit
Vary visual elements:
- Geometry choice: Not everything needs to be a cube. Explore spheres, tori, icosahedra
- Material style: Mix flat shaded, glossy, metallic, wireframe
- Color palettes: Use complementary, analogous, or monochromatic schemes
- Animation style: Rotation, oscillation, wave motion, mouse tracking
Avoid converging on:
- Default green cube as first example every time
- Same camera angle (front-facing, z=5)
- Identical lighting setup (always directional light at 1,1,1)
重要提示:每个Three.js应用都应具备独特性,符合场景需求。
按场景调整:
- 作品集/展示案例:优雅、流畅的动画,柔和的配色
- 游戏/交互式应用:鲜艳的颜色,灵敏的控制,粒子效果
- 数据可视化:简洁的线条,网格辅助,清晰的标签
- 背景效果:微妙、缓慢的移动,深色/渐变背景
- 产品展示:真实感光照,PBR材质,流畅的轨道控制
视觉元素调整:
- 几何体选择:不要局限于立方体,尝试球体、圆环、二十面体等
- 材质风格:混合使用平光、高光、金属质感、线框等效果
- 配色方案:使用互补色、类似色或单色方案
- 动画风格:旋转、振荡、波浪运动、鼠标追踪等
避免同质化:
- 不要每次都使用默认的绿色立方体作为第一个示例
- 不要总是使用相同的相机角度(正面朝向,z=5)
- 不要总是使用相同的光照设置(始终使用位于(1,1,1)的平行光)
Remember
注意事项
Three.js is a tool for interactive 3D on the web.
Effective Three.js apps:
- Start with the scene graph mental model
- Use primitives as building blocks
- Keep animations simple and performant
- Vary visual style based on purpose
- Import from modern ES module paths
Modern Three.js (r150+) uses ES modules from package or CDN. CommonJS patterns and global variable are legacy.
threeTHREEFor advanced topics (GLTF models, shaders, post-processing), see references/advanced-topics.md.
Claude is capable of creating elegant, performant 3D web experiences. These patterns guide the way—they don't limit the result.
Three.js 是用于在网页上实现交互式3D效果的工具。
高效的Three.js应用需遵循:
- 从场景图思维模型出发
- 以基础几何体为构建块
- 保持动画简洁且高性能
- 根据应用目的调整视觉风格
- 使用现代ES模块路径导入资源
现代Three.js(r150+版本)使用包或CDN提供的ES模块。CommonJS模式和全局变量已属于旧版用法。
threeTHREE如需了解高级主题(GLTF模型、着色器、后期处理),请参考references/advanced-topics.md。
Claude 能够创建优雅、高性能的3D网页体验。这些模式是指导方向——而非限制结果。