引言
随着 Web 技术的飞速发展,3D 图形在前端领域的应用越来越广泛。从产品展示到数据可视化,从游戏开发到虚拟现实,3D 技术正在重塑我们的数字体验。本文将带你入门 Three.js,这个最流行的 WebGL 库,让你快速掌握创建 3D 场景的核心技能。
什么是 Three.js?
Three.js 是一个基于 WebGL 的 JavaScript 3D 库,它简化了 WebGL 的复杂 API,让开发者能够用更少的代码创建令人惊叹的 3D 场景。
核心优势:
- 简洁的 API 设计
- 丰富的内置几何体和材质
- 强大的光照系统
- 完善的动画支持
- 活跃的社区生态
快速开始
1. 基础场景搭建
xml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js 入门</title>
<style>
body { margin: 0; }
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();
scene.background = new THREE.Color(0x87CEEB); // 天空蓝背景
// 创建相机
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();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
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>
2. 核心概念解析
场景 (Scene)
场景是 3D 世界的容器,所有物体、灯光、相机都放在场景中。
ini
const scene = new THREE.Scene();
// 添加雾效果
scene.fog = new THREE.Fog(0x87CEEB, 1, 10);
相机 (Camera)
相机决定了我们如何观察 3D 世界。
arduino
// 透视相机 - 最常用
const perspectiveCamera = new THREE.PerspectiveCamera(
fov, aspect, near, far
);
// 正交相机 - 用于 2D 或技术图纸
const orthoCamera = new THREE.OrthographicCamera(
left, right, top, bottom, near, far
);
渲染器 (Renderer)
渲染器负责将场景绘制到屏幕上。
php
const renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
alpha: true, // 支持透明背景
powerPreference: 'high-performance'
});
3. 几何体与材质
常用几何体
arduino
// 立方体
const box = new THREE.BoxGeometry(width, height, depth);
// 球体
const sphere = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
// 圆柱体
const cylinder = new THREE.CylinderGeometry(radiusTop, radiusBottom, height);
// 圆环
const torus = new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments);
// 平面
const plane = new THREE.PlaneGeometry(width, height);
材质类型
php
// 基础材质 - 不受光照影响
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
// 标准材质 - 物理光照
const standardMaterial = new THREE.MeshStandardMaterial({
color: 0x00ff00,
roughness: 0.5, // 粗糙度
metalness: 0.1 // 金属度
});
// 网格材质 - 线框模式
const meshMaterial = new THREE.MeshBasicMaterial({
color: 0x0000ff,
wireframe: true
});
// Phong 材质 - 光滑表面
const phongMaterial = new THREE.MeshPhongMaterial({
color: 0xffff00,
shininess: 100 // 高光强度
});
4. 光照系统
ini
// 环境光 - 全局照明
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 平行光 - 模拟太阳光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
scene.add(directionalLight);
// 点光源 - 类似灯泡
const pointLight = new THREE.PointLight(0xff0000, 1, 100);
pointLight.position.set(0, 5, 0);
scene.add(pointLight);
// 聚光灯 - 舞台灯光效果
const spotLight = new THREE.SpotLight(0x00ff00, 1);
spotLight.position.set(0, 10, 0);
spotLight.angle = Math.PI / 4;
spotLight.penumbra = 0.1;
scene.add(spotLight);
5. 动画与交互
基础动画
ini
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
// 旋转
cube.rotation.y += delta;
// 缩放
sphere.scale.x = Math.sin(Date.now() * 0.001);
sphere.scale.y = Math.sin(Date.now() * 0.001);
// 位移
torus.position.x = Math.sin(Date.now() * 0.0005) * 2;
renderer.render(scene, camera);
}
鼠标交互
ini
const raycaster = new THREE.Raycaster();
const mouse = new THREE.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) {
// 点击到了物体
intersects[0].object.material.color.set(0xff0000);
}
});
// 鼠标移动
window.addEventListener('mousemove', (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
6. 加载外部模型
ini
import { GLTFLoader } from 'https://unpkg.com/three@0.160.0/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load('path/to/model.glb', (gltf) => {
const model = gltf.scene;
// 调整位置和缩放
model.position.set(0, 0, 0);
model.scale.set(1, 1, 1);
// 添加动画
const mixer = new THREE.AnimationMixer(model);
const action = mixer.clipAction(gltf.animations[0]);
action.play();
scene.add(model);
// 在动画循环中更新
function animate() {
requestAnimationFrame(animate);
mixer.update(clock.getDelta());
renderer.render(scene, camera);
}
});
实战案例:创建 3D 产品展示
ini
// 创建产品展示场景
function createProductShowcase() {
const scene = new THREE.Scene();
// 添加网格地面
const gridHelper = new THREE.GridHelper(20, 20);
scene.add(gridHelper);
// 添加多个物体
const objects = [];
const geometries = [
new THREE.BoxGeometry(1, 1, 1),
new THREE.SphereGeometry(0.5, 32, 32),
new THREE.TorusGeometry(0.5, 0.2, 16, 100)
];
geometries.forEach((geo, index) => {
const material = new THREE.MeshStandardMaterial({
color: new THREE.Color().setHSL(index / geometries.length, 1, 0.5),
roughness: 0.3,
metalness: 0.7
});
const mesh = new THREE.Mesh(geo, material);
mesh.position.x = (index - 1) * 2;
mesh.position.y = 0.5;
scene.add(mesh);
objects.push(mesh);
});
// 添加灯光
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 10, 5);
scene.add(light);
return { scene, objects };
}
性能优化建议
- 使用几何体复用:多个相同物体共享同一个几何体和材质
- 实例化渲染 :使用
InstancedMesh渲染大量相同物体 - 纹理压缩:使用压缩纹理格式(如 DDS、KTX2)
- LOD 技术:根据距离使用不同精度的模型
- 裁剪不必要的物体:使用视锥体裁剪
总结
Three.js 为前端开发者提供了强大的 3D 创作能力。通过本文的介绍,你已经掌握了:
- 场景、相机、渲染器的基础搭建
- 几何体和材质的使用
- 光照系统的配置
- 动画和交互的实现
- 外部模型的加载