
关于
Three.js 动画 - 关键帧动画、骨骼动画、变形目标、动画混合。适用于对象动画、播放 GLTF 动画、创建程序化运动或混合动画。
name: threejs-animation description: Three.js 动画 - 关键帧动画、骨骼动画、变形目标、动画混合。适用于对象动画、播放 GLTF 动画、创建程序化运动或混合动画。 risk: unknown source: community
Three.js 动画
适用场景
- 需要在 Three.js 中为对象、骨骼、变形目标或导入的 GLTF 动画制作动画。
- 任务涉及混合器、片段、关键帧、程序化运动或动画混合。
- 正在构建 Three.js 场景中的运动行为,而非仅静态渲染。
快速开始
import * as THREE from "three";
// Simple procedural animation with Timer (recommended in r183)
const timer = new THREE.Timer();
renderer.setAnimationLoop(() => {
timer.update();
const delta = timer.getDelta();
const elapsed = timer.getElapsed();
mesh.rotation.y += delta;
mesh.position.y = Math.sin(elapsed) * 0.5;
renderer.render(scene, camera);
});
注意: 从 r183 起推荐使用 THREE.Timer 替代 THREE.Clock。Timer 在页面隐藏时会暂停,且 API 更简洁。THREE.Clock 仍可使用但已被视为遗留方案。
动画系统概述
Three.js 动画系统有三个主要组件:
- AnimationClip - 关键帧数据容器
- AnimationMixer - 在根对象上播放动画
- AnimationAction - 控制片段的播放
AnimationClip
存储关键帧动画数据。
// Create animation clip
const times = [0, 1, 2]; // Keyframe times (seconds)
const values = [0, 1, 0]; // Values at each keyframe
const track = new THREE.NumberKeyframeTrack(
".position[y]", // Property path
times,
values,
);
const clip = new THREE.AnimationClip("bounce", 2, [track]);
关键帧轨道类型
// Number track (single value)
new THREE.NumberKeyframeTrack(".opacity", times, [1, 0]);
new THREE.NumberKeyframeTrack(".material.opacity", times, [1, 0]);
// Vector track (position, scale)
new THREE.VectorKeyframeTrack(".position", times, [
0, 0, 0, // t=0
1, 2, 0, // t=1
0, 0, 0, // t=2
]);
// Quaternion track (rotation)
const q1 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));
const q2 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0));
new THREE.QuaternionKeyframeTrack(
".quaternion",
[0, 1],
[q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w],
);
// Color track
new THREE.ColorKeyframeTrack(".material.color", times, [
1, 0, 0, // red
0, 1, 0, // green
0, 0, 1, // blue
]);
// Boolean track
new THREE.BooleanKeyframeTrack(".visible", [0, 0.5, 1], [true, false, true]);
// String track (for morph targets)
new THREE.StringKeyframeTrack(
".morphTargetInfluences[smile]",
[0, 1],
["0", "1"],
);
插值模式
const track = new THREE.VectorKeyframeTrack(".position", times, values);
// Interpolation
track.setInterpolation(THREE.InterpolateLinear); // Default
track.setInterpolation(THREE.InterpolateSmooth); // Cubic spline
track.setInterpolation(THREE.InterpolateDiscrete); // Step function
贝塞尔插值 (r183)
Three.js r183 新增 THREE.BezierInterpolant,支持关键帧轨道中的贝塞尔曲线插值,通过切线控制实现更平滑的动画曲线。
AnimationMixer
在对象及其子对象上播放动画。
const mixer = new THREE.AnimationMixer(model);
// Create action from clip
const action = mixer.clipAction(clip);
action.play();
// Update in animation loop
function animate() {
const delta = clock.getDelta();
mixer.update(delta); // Required!
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
混合器事件
mixer.addEventListener("finished", (e) => {
console.log("Animation finished:", e.action.getClip().name);
});
mixer.addEventListener("loop", (e) => {
console.log("Animation looped:", e.action.getClip().name);
});
AnimationAction
控制动画片段的播放。
const action = mixer.clipAction(clip);
// Playback control
action.play();
action.stop();
action.reset();
action.halt(fadeOutDuration);
// Playback state
action.isRunning();
action.isScheduled();
// Time control
action.time = 0.5; // Current time
action.timeScale = 1; // Playback speed (negative = reverse)
action.paused = false;
// Weight (for blending)
action.weight = 1; // 0-1, contribution to final pose
action.setEffectiveWeight(1);
// Loop modes
action.loop = THREE.LoopRepeat; // Default: loop forever
action.loop = THREE.LoopOnce; // Play once and stop
action.loop = THREE.LoopPingPong; // Alternate forward/backward
action.repetitions = 3; // Number of loops (Infinity default)
// Clamping
action.clampWhenFinished = true; // Hold last frame when done
// Blending
action.blendMode = THREE.NormalAnimationBlendMode;
action.blendMode = THREE.AdditiveAnimationBlendMode;
淡入/淡出
// Fade in
action.fadeIn(0.5).play();
兼容工具
Claude CodeCursor
标签
前端开发