在 Three.js 动画系统中,AnimationClip
是用于存储关键帧动画数据的核心组件。通过 AnimationClip
,我们可以创建复杂的动画,并将其应用于场景中的对象。AnimationClip
可以与 AnimationMixer
和 AnimationAction
结合使用,以提供强大的动画控制。
本文将详细介绍 AnimationClip
的用法,包括它的属性、方法及如何与其他 Three.js 组件配合使用。通过多个示例演示如何使用 AnimationClip
来创建和控制动画。
AnimationClip
是一种定义动画的类,它包含了一个或多个 KeyframeTrack
(关键帧轨迹),每个 KeyframeTrack
定义了动画中某个属性的变化。通过设置多个关键帧,可以让属性在不同的时间点上发生变化,从而创建动画效果。
AnimationClip
的核心组件KeyframeTrack
有 VectorKeyframeTrack
(用于位置变化)、QuaternionKeyframeTrack
(用于旋转变化)、ColorKeyframeTrack
(用于颜色变化)等。AnimationClip
的播放和控制。AnimationClip
通常通过关键帧轨迹(KeyframeTrack
)来定义。让我们通过一个简单的示例展示如何创建一个 AnimationClip
。
首先,我们需要创建一个基本的场景,包括一个立方体对象,并通过摄像机和渲染器进行渲染。
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);
camera.position.z = 5;
接下来,我们为动画创建一个立方体对象:
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);
KeyframeTrack
是定义动画变化的轨迹。在这个示例中,我们将使用 VectorKeyframeTrack
来控制立方体沿 Y 轴的运动。
const times = [0, 1, 2]; // 定义动画的时间点
const values = [0, 0, 0, 0, 2, 0, 0, 0, 0]; // 定义在每个时间点的位置
const positionKF = new THREE.VectorKeyframeTrack('.position', times, values);
接下来,我们使用关键帧轨迹创建 AnimationClip
。AnimationClip
的第一个参数是名称,第二个参数是动画的持续时间,第三个参数是包含的关键帧轨迹数组。
const clip = new THREE.AnimationClip('moveUpAndDown', 2, [positionKF]);
AnimationMixer
是管理和播放动画的工具。为了让动画播放,我们需要创建一个 AnimationMixer
,然后通过它来生成 AnimationAction
并播放 AnimationClip
。
const mixer = new THREE.AnimationMixer(cube);
通过 AnimationMixer
的 clipAction
方法,可以创建一个 AnimationAction
对象,接着调用 play()
方法来播放动画。
const action = mixer.clipAction(clip);
action.play();
为了让动画正常播放,我们需要在渲染循环中不断更新 AnimationMixer
。
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta); // 更新动画
renderer.render(scene, camera);
}
animate();
到这里,我们已经成功创建了一个基本的动画,立方体会在 Y 轴上来回移动。
AnimationClip
提供了多种属性和方法,允许我们对动画进行更复杂的控制。接下来我们将详细介绍这些属性和方法,并展示如何使用它们。
duration
duration
表示动画的时长。可以通过设置此属性来更改动画的持续时间。
clip.duration = 3; // 将动画时长设置为 3 秒
tracks
tracks
是一个包含所有 KeyframeTrack
的数组。可以通过它来查看和修改动画中包含的所有轨迹。
console.log(clip.tracks); // 查看动画的关键帧轨迹
resetDuration()
resetDuration()
方法会根据关键帧轨迹的时间自动调整动画的持续时间。
clip.resetDuration();
trim()
trim()
方法会移除动画中多余的时间段,仅保留关键帧定义的有效部分。这在需要裁剪动画时非常有用。
clip.trim();
optimize()
optimize()
方法可以优化动画,移除冗余的关键帧,从而减少动画数据的大小。对于复杂动画来说,这可以提高性能。
clip.optimize();
在许多情况下,一个对象可能会有多个动画。Three.js 允许我们为同一个对象创建多个 AnimationClip
,并通过 AnimationAction
控制不同动画之间的过渡和混合。
我们再创建一个动画,使立方体沿 X 轴移动:
const positionKF2 = new THREE.VectorKeyframeTrack(
'.position',
[0, 1, 2],
[0, 0, 0, 2, 0, 0, 0, 0, 0]
);
const clip2 = new THREE.AnimationClip('moveSideToSide', 2, [positionKF2]);
我们可以通过 AnimationMixer
创建多个 AnimationAction
来播放不同的动画,并通过调整它们的播放时间和权重来实现动画的混合。
const action2 = mixer.clipAction(clip2);
action2.play();
通过调整动画的权重,可以让两个动画平滑过渡或混合播放。如下代码展示了如何让两个动画同时播放,并通过权重控制它们的影响。
action.weight = 0.5;
action2.weight = 0.5;
在这个例子中,立方体将会同时沿 Y 轴和 X 轴移动,产生一个对角线的移动效果。
在动画中,我们通常希望控制动画的循环方式。AnimationClip
提供了多种循环模式,允许我们灵活控制动画的播放行为。
Three.js 提供了三种主要的循环模式:
THREE.LoopOnce
:动画播放一次后停止。THREE.LoopRepeat
:动画无限循环。THREE.LoopPingPong
:动画往复播放。我们可以通过 AnimationAction
的 setLoop
方法来设置动画的循环方式:
action.setLoop(THREE.LoopPingPong, Infinity); // 动画往复循环
通过 AnimationMixer
,我们可以监听动画的开始、结束、循环等事件。以下示例展示了如何监听动画播放的完成事件:
mixer.addEventListener('finished', (event) => {
console.log('动画播放完成');
});
以下是一个完整的示例,展示了如何使用 AnimationClip
和 AnimationMixer
创建和控制多个动画:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js AnimationClip 示例</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>
<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 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 positionKF = new THREE.VectorKeyframeTrack('.position', [0, 1, 2], [0, 0, 0, 0, 2, 0, 0, 0, 0]);
const clip = new THREE.AnimationClip('moveUpAndDown', 2, [positionKF]);
const positionKF2 = new THREE.VectorKeyframeTrack('.position', [0, 1, 2], [0, 0, 0, 2, 0, 0, 0, 0, 0]);
const clip2 = new THREE.AnimationClip('moveSideToSide', 2, [positionKF2]);
const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
const action2 = mixer.clipAction(clip2);
action.play();
action2.play();
action.weight = 0.5;
action2.weight = 0.5;
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta);
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>
AnimationClip
是 Three.js 动画系统的核心组件之一,允许开发者定义复杂的动画。本文详细介绍了如何创建和使用 AnimationClip
,并结合 AnimationMixer
和 AnimationAction
实现了多种动画控制方式。通过优化、裁剪和混合动画,可以实现更加灵活的动画效果。希望本文能够帮助你更好地理解和使用 Three.js 的动画系统。
如有任何问题或建议,欢迎留言讨论!