前言
在上一篇文章中,我们学习了 Three.js 的基础概念,包括场景、相机、几何体、材质、网格和渲染器。这篇文章我们将深入讲解 对象的变换(Transform) 和 动画(Animation),并结合代码示例帮助你更好地理解这些核心概念。
Transform:对象的变换
在 3D 场景中,对象的变换包括 位置(Position) 、缩放(Scale) 和 旋转(Rotation)。Three.js 提供了丰富的 API 来操作这些属性,以下是具体用法。
1. 距离与位置
获取距离
.position.length()
:返回对象到原点(0,0,0)的距离。.position.distanceTo(object.position)
:返回两个对象之间的距离。
归一化
.position.normalize()
:将向量归一化为单位向量(长度为 1)。
设置位置
-
mesh.position.set(x, y, z)
:一次性设置对象的坐标。 -
单独设置轴:
jsmesh.position.x = 1; // 设置 x 轴 mesh.position.y = 1; // 设置 y 轴 mesh.position.z = 1; // 设置 z 轴
示例代码
js
// 创建一个立方体
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
// 设置立方体位置
cube.position.set(2, 0, 0); // 移动到 x=2 的位置
// 添加到场景
scene.add(cube);
2. 轴辅助工具
AxisHelper
new THREE.AxisHelper(size)
:创建一个坐标轴辅助工具,帮助可视化 3D 空间中的方向。size
:坐标轴的长度(默认 1)。
示例代码
js
// 创建坐标轴辅助工具(长度为 5)
const axesHelper = new THREE.AxisHelper(5);
scene.add(axesHelper);
正常不调整xy方向是看不到三条轴线的
3. 定位对象
缩放(Scale)
.scale.x/y/z
:单独设置缩放比例。.scale.set(x, y, z)
:一次性设置所有轴的缩放。
旋转(Rotation)
.rotation.x/y/z
:单独设置旋转角度(弧度制)。.rotation.set(x, y, z)
:一次性设置所有轴的旋转。.rotation.reorder('XYZ')
:调整旋转顺序(解决旋转依赖问题)。
lookAt()
object.lookAt(target)
:让对象朝向目标点(常用于相机或物体对齐)。
组(Group)
-
new THREE.Group()
:创建一个组,可将多个对象组合在一起,统一管理位置、旋转、缩放。jsconst group = new THREE.Group(); group.add(cube1); group.add(cube2); scene.add(group);
示例代码
js
// 缩放立方体
cube.scale.set(2, 1, 0.5); // x 轴放大 2 倍,y 轴不变,z 轴缩小一半
// 旋转立方体
cube.rotation.set(Math.PI / 4, 0, 0); // 绕 x 轴旋转 45 度
// 使用组管理多个对象
const group = new THREE.Group();
group.add(cube);
group.add(axesHelper);
scene.add(group);
Animation:动画
Three.js 的动画核心在于 渲染循环(Render Loop) 和 时间控制 。我们可以通过 requestAnimationFrame
或 THREE.Clock
实现平滑动画。
1. 渲染循环
基本原理
- 使用
requestAnimationFrame
不断调用渲染函数,更新对象状态。 - 每帧更新对象的位置、旋转等属性。
示例代码
js
// 初始化时钟
const clock = new THREE.Clock();
// 渲染循环函数
function animate() {
requestAnimationFrame(animate);
// 获取经过的时间(秒)
const elapsedTime = clock.getElapsedTime();
// 更新对象位置
cube.rotation.y += 0.01; // 每帧绕 y 轴旋转
cube.position.y = Math.sin(elapsedTime); // 垂直运动
// 渲染
renderer.render(scene, camera);
}
// 启动渲染循环
animate();
2. 时间戳与时间控制
使用 Date.now()
Date.now()
返回当前时间戳(毫秒),可用于计算帧间隔时间。deltaTime = currentTime - lastTime
:计算两帧之间的时间差。
使用 THREE.Clock
const clock = new THREE.Clock()
:Three.js 提供的时钟工具。clock.getElapsedTime()
:获取从时钟启动到当前的总时间(秒)。
示例代码
js
let time = Date.now();
function animate() {
requestAnimationFrame(animate);
const currentTime = Date.now();
const deltaTime = currentTime - time;
time = currentTime;
console.log(`每帧耗时:${deltaTime}ms`);
renderer.render(scene, camera);
}
animate();
3. 使用 GSAP 实现动画
GSAP(GreenSock Animation Platform)是一个强大的动画库,可以简化 Three.js 动画的创建。
示例代码
js
// 引入 GSAP
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
// 动画示例:立方体移动
gsap.to(cube.position, {
duration: 1, // 动画持续时间
delay: 1, // 延迟 1 秒开始
x: 2, // 移动到 x=2
ease: "power1.inOut" // 缓动函数
});
gsap.to(cube.position, {
duration: 1,
delay: 2,
x: 0, // 回到 x=0
ease: "power1.inOut"
});
完整代码示例

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 Transform & Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script>
// 初始化场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建立方体
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);
// 坐标轴辅助工具
const axesHelper = new THREE.AxisHelper(5);
scene.add(axesHelper);
// 使用 GSAP 动画
gsap.to(cube.position, {
duration: 1,
delay: 1,
x: 2,
ease: "power1.inOut"
});
gsap.to(cube.position, {
duration: 1,
delay: 2,
x: 0,
ease: "power1.inOut"
});
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
留下一个简单思考题如何实现下面的效果:
结语
通过这篇文章,我们学习了 Three.js 中对象的变换(Transform)和动画(Animation)的核心概念,并通过代码示例展示了如何实现这些功能。