Three.js 提供了强大的动画系统,使得在 3D 场景中为对象添加动画变得简单而高效。本文将详细介绍 Three.js 动画系统的基本概念、常用方法,以及如何在 Three.js 中实现动画效果,包括关键帧动画、混合动画和使用动画控制器。
Three.js 的动画系统主要由以下几个部分组成:
确保在 HTML 文件中引入 Three.js:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 动画系统示例</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
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);
document.body.appendChild(renderer.domElement);
我们将在场景中添加一个立方体,以便演示动画效果:
const geometryCube = new THREE.BoxGeometry(1, 1, 1);
const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometryCube, materialCube);
scene.add(cube);
camera.position.z = 5;
创建一个关键帧动画以使立方体在 Y 轴上上下移动:
const mixer = new THREE.AnimationMixer(cube);
const positionKF = new THREE.VectorKeyframeTrack(
'.position',
[0, 1, 2], // 时间点
[0, 2, 0, // 在这些时间点的 Y 坐标
0, -2, 0]
);
const clip = new THREE.AnimationClip('moveCube', 2, [positionKF]);
const action = mixer.clipAction(clip);
action.play(); // 播放动画
在渲染循环中更新动画混合器:
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta(); // 获取时间间隔
mixer.update(delta); // 更新动画混合器
renderer.render(scene, camera);
}
const clock = new THREE.Clock(); // 创建时钟
animate();
Three.js 还提供了动画控制器,使得控制动画更加灵活。
创建一个控制器并将其与动画混合器关联:
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼
controls.dampingFactor = 0.25;
在渲染循环中更新控制器:
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta);
controls.update(); // 更新控制器
renderer.render(scene, camera);
}
Three.js 的动画系统还支持从模型文件中加载动画,下面将展示如何使用 GLTF 模型及其动画。
使用 GLTFLoader
加载模型及其动画:
const loader = new THREE.GLTFLoader();
loader.load('path/to/your/model.glb', (gltf) => {
const model = gltf.scene;
scene.add(model);
const mixer = new THREE.AnimationMixer(model);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
});
在渲染循环中继续更新混合器,以确保动画的流畅播放:
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta); // 更新混合器
controls.update();
renderer.render(scene, camera);
}
以下是一个完整的示例,展示了如何在 Three.js 中使用动画系统:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 动画系统示例</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/jsm/loaders/GLTFLoader.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/jsm/controls/OrbitControls.js"></script>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script>
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);
document.body.appendChild(renderer.domElement);
const geometryCube = new THREE.BoxGeometry(1, 1, 1);
const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometryCube, materialCube);
scene.add(cube);
camera.position.z = 5;
// 动画
const mixer = new THREE.AnimationMixer(cube);
const positionKF = new THREE.VectorKeyframeTrack(
'.position',
[0, 1, 2],
[0, 2, 0, 0, -2, 0]
);
const clip = new THREE.AnimationClip('moveCube', 2, [positionKF]);
const action = mixer.clipAction(clip);
action.play();
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta);
controls.update();
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
确保在窗口调整大小时更新渲染器和摄像机:
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
在本文中,我们详细探讨了如何在 Three.js 中使用动画系统,包括关键帧动画、混合动画、模型动画的加载及控制。通过这些示例,希望你能够掌握 Three.js 动画系统的使用,创造出更加生动的 3D 场景。若有任何问题或建议,欢迎在评论区留言讨论!