Three.js 模型动画

提示词

PLAINTEXT
1
使用 Three.js 加载带动画的 GLTF 模型,使用 AnimationMixer 播放模型动画,支持单动画和多动画同时播放。

效果描述

这是一个展示如何加载和播放 GLTF 模型动画的示例,支持单动画播放和多动画同时播放。

效果特性

  • GLTF 动画加载:加载带动画的 GLTF 模型
  • 单动画播放:播放单个动画
  • 多动画播放:同时播放多个动画
  • 动画控制:使用 GUI 控制动画播放
  • 动画混合:多个动画同时播放
  • 动画停止:定时停止动画

核心参数

参数 说明
模型路径 /files/model/Soldier.glb GLTF 模型文件
播放速度 1.0 动画播放速度
停留最后一帧 true 动画完成后停留在最后一帧
循环模式 LoopRepeat 动画循环模式
停止时间 4000ms 多动画停止时间

核心代码解析

动画播放函数

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function modelAnimationPlay(group) {
    const clock = new THREE.Clock();
    const mixer = new THREE.AnimationMixer(group);

    group.mixerAnimateRender = () => {
        const deltaTime = clock.getDelta();
        mixer.update(deltaTime);
    };

    const actions = group.actionIndexs
        .map((i, k) => {
            if (i) {
                const animationAction = mixer.clipAction(group.animations[k]);
                animationAction.loop = THREE.LoopRepeat;
                animationAction.time = 0;
                animationAction.timeScale = 1; // 播放速度
                animationAction.clampWhenFinished = true; // 停留到最后一帧
                animationAction.play();
                return animationAction;
            }
        })
        .filter((i) => i);

    !mixerFrames.find((i) => i === group) && mixerFrames.push(group);

    return { actions, mixer };
}

GUI 动画控制

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const createModeAnimates = (model) => {
    model.animations.forEach((_, k) => {
        gui.add({
            fn: () => {
                model.actionIndexs.forEach((_, _k, arr) => (arr[_k] = _k === k));
                modelAnimationPlay(model, model.animations);
            },
        }, "fn").name(`单动画${k}`);
    });

    gui.add({
        fn: () => {
            const _actions = [1, 2]; // 同时播放 第三个和第四个动画
            model.actionIndexs.forEach((_, k, arr) => (arr[k] = _actions.includes(k)));
            const { actions } = modelAnimationPlay(model, model.animations);
            setTimeout(() => actions.forEach((v) => v.stop()), 4000);
        },
    }, "fn").name("1, 2动画同时播放");
};

动画循环更新

JAVASCRIPT
1
2
3
4
5
function animate() {
    requestAnimationFrame(animate);
    mixerFrames.forEach((i) => i?.mixerAnimateRender?.());
    renderer.render(scene, camera);
}

技术亮点

  1. AnimationMixer:使用 AnimationMixer 管理动画
  2. clipAction:创建动画动作
  3. 动画混合:多个动画同时播放
  4. 时间控制:使用 Clock 获取时间增量
  5. 动画状态:使用数组跟踪动画状态

调试技巧

  1. 播放速度:调整 timeScale 控制播放速度
  2. 循环模式:调整 loop 控制循环行为
  3. 停留帧:clampWhenFinished 控制是否停留
  4. 动画索引:确保动画索引正确
  5. 停止时间:调整 setTimeout 时间控制停止时机

扩展方向

  1. 动画过渡:使用 crossFadeTo 实现动画过渡
  2. 动画权重:调整动画权重实现混合
  3. 动画速度:动态调整动画播放速度
  4. 动画事件:监听动画事件
  5. 动画序列:创建动画播放序列

本文档由 ThreeLab 编辑整理,如需转载,请注明出处。