在 Three.js 中,如果一个 3D 模型文件包含多个动画(例如 GLTF 文件中的多个 AnimationClip
),你可以将这些动画收集到一个数组中,并通过代码逐一调用或管理它们。以下是详细的说明和实现方法。
结论
可以将模型文件中的多个动画收集为一个数组,并在 Three.js 中通过 THREE.AnimationMixer
和 THREE.AnimationAction
来管理和播放这些动画。
详细展开
1. 加载模型中的动画剪辑
当使用 GLTFLoader
加载模型时,模型文件中的所有动画剪辑会被自动解析并存储在 gltf.animations
数组中。你可以直接访问这个数组来获取所有动画。
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
const model = gltf.scene; // 获取模型对象
const animations = gltf.animations; // 获取动画剪辑数组
console.log('模型包含的动画:', animations);
});
2. 创建动画混合器
为了播放动画,需要为模型创建一个 THREE.AnimationMixer
实例。每个动画剪辑可以通过 mixer.clipAction(clip)
方法创建一个对应的 AnimationAction
对象。
const mixer = new THREE.AnimationMixer(model); // 创建动画混合器
3. 将动画收集到数组中
你可以将所有动画剪辑的 AnimationAction
对象存储在一个数组中,以便后续管理和调用。
const animationActions = []; // 用于存储所有动画动作
animations.forEach((clip, index) => {
const action = mixer.clipAction(clip); // 为每个动画剪辑创建动作
animationActions.push(action); // 将动作添加到数组中
console.log(`动画 ${index}:`, clip.name || `未命名动画 ${index}`);
});
4. 播放特定动画
通过索引或名称从数组中选择某个动画并播放。
// 播放第一个动画
if (animationActions.length > 0) {
animationActions[0].play();
}
// 或者根据名称播放动画
const targetAnimationName = 'run'; // 假设有一个名为 "run" 的动画
const targetAction = animationActions.find(action => action.getClip().name === targetAnimationName);
if (targetAction) {
targetAction.play();
} else {
console.warn(`未找到名为 "${targetAnimationName}" 的动画`);
}
5. 切换动画
可以通过停止当前动画并播放新动画来实现动画切换。
function switchToAnimation(index) {
// 停止所有正在播放的动画
animationActions.forEach(action => action.stop());
// 播放指定索引的动画
if (animationActions[index]) {
animationActions[index].play();
} else {
console.warn(`索引 ${index} 超出范围`);
}
}
// 示例:切换到第二个动画
switchToAnimation(1);
6. 淡入淡出切换动画
使用 crossFadeTo
方法可以在两个动画之间进行平滑过渡。
function fadeToAnimation(targetIndex, duration = 1) {
// 找到目标动画
const targetAction = animationActions[targetIndex];
if (!targetAction) {
console.warn(`索引 ${targetIndex} 超出范围`);
return;
}
// 遍历所有动画,停止其他动画并淡入目标动画
animationActions.forEach((action, index) => {
if (index !== targetIndex && action.isRunning()) {
action.crossFadeTo(targetAction, duration); // 淡出当前动画
}
});
targetAction.play(); // 播放目标动画
}
// 示例:淡入到第三个动画,持续时间 2 秒
fadeToAnimation(2, 2);
7. 完整示例代码
以下是一个完整的示例,展示如何加载模型、收集动画并切换动画:
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
const model = gltf.scene;
scene.add(model);
const animations = gltf.animations; // 获取动画剪辑数组
const mixer = new THREE.AnimationMixer(model); // 创建动画混合器
const animationActions = []; // 存储动画动作
animations.forEach((clip, index) => {
const action = mixer.clipAction(clip); // 创建动画动作
animationActions.push(action);
console.log(`加载动画 ${index}:`, clip.name || `未命名动画 ${index}`);
});
// 默认播放第一个动画
if (animationActions.length > 0) {
animationActions[0].play();
}
// 切换到第二个动画
function switchToSecondAnimation() {
if (animationActions.length > 1) {
switchToAnimation(1);
}
}
// 更新动画
let clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
mixer.update(clock.getDelta()); // 更新动画混合器
renderer.render(scene, camera);
}
animate();
});
总结
在 Three.js 中,可以将模型文件中的多个动画收集到一个数组中,并通过 THREE.AnimationMixer
和 THREE.AnimationAction
来管理和播放这些动画。通过这种方式,你可以轻松实现动画的切换、淡入淡出等效果,从而增强场景的交互性和视觉表现力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!