关键帧动画

164 阅读2分钟

 创建关键帧动画AnimationClip

### 1. 创建关键帧动画`AnimationClip`
// 给需要设置关键帧动画的模型命名
mesh.name = "Box";
const times = [0, 3, 6]; //时间轴上,设置三个时刻0、3、6秒
// times中三个不同时间点,物体分别对应values中的三个xyz坐标
const values = [0, 0, 0, 100, 0, 0, 0, 0, 100];
// 0~3秒,物体从(0,0,0)逐渐移动到(100,0,0),3~6秒逐渐从(100,0,0)移动到(0,0,100)
const posKF = new THREE.KeyframeTrack('Box.position', times, values);
// 从2秒到5秒,物体从红色逐渐变化为蓝色
const colorKF = new THREE.KeyframeTrack('Box.material.color', [2, 5], [1, 0, 0, 0, 0, 1]);
// 1.3 基于关键帧数据,创建一个clip关键帧动画对象,命名"test",持续时间6秒。
const clip = new THREE.AnimationClip("test", 6, [posKF, colorKF]);

AnimationMixer播放关键帧动画AnimationClip

//包含关键帧动画的模型对象作为AnimationMixer的参数创建一个播放器mixer
const mixer = new THREE.AnimationMixer(mesh);
//AnimationMixer的`.clipAction()`返回一个AnimationAction对象
const clipAction = mixer.clipAction(clip); 
//.play()控制动画播放,默认循环播放
clipAction.play(); 

mixer.update()更新播放器AnimationMixer时间

### `mixer.update()`更新播放器`AnimationMixer`时间
function loop() {
    requestAnimationFrame(loop);
    const frameT = clock.getDelta();
    // 更新播放器相关的时间
    mixer.update(frameT);
}
loop();

动画播放(暂停、倍速、循环)

const clipAction = mixer.clipAction(clip);
//.play()控制动画播放,默认循环播放
clipAction.play();
//不循环播放
clipAction.loop = THREE.LoopOnce; 
//不循环播放,执行一次后默认回到动画开头
clipAction.loop = THREE.LoopOnce; 

动画播放(拖动任意时间状态)

//AnimationAction设置开始播放时间:从1秒时刻对应动画开始播放
clipAction.time = 1; 
//AnimationClip设置播放结束时间:到5秒时刻对应的动画状态停止
clip.duration = 5;

//在暂停情况下,设置.time属性,把动画定位在任意时刻
clipAction.paused = true;
clipAction.time = 1;//物体状态为动画1秒对应状态
clipAction.time = 3;//物体状态为动画3秒对应状态

gui.add(clipAction, 'time', 0, 6).step(0.1);

解析外部模型关键帧动画

let mixer = null; //声明一个播放器变量
loader.load("../工厂.glb", function (gltf) { 
    model.add(gltf.scene);
     //包含帧动画的模型作为参数创建一个播放器
     mixer = new THREE.AnimationMixer(gltf.scene);
    //  获取gltf.animations[0]的第一个clip动画对象
     const clipAction = mixer.clipAction(gltf.animations[0]);//创建动画clipAction对象
     clipAction.play();//播放动画
})

 // 创建一个时钟对象Clock
 const clock = new THREE.Clock();
 function render() {
     requestAnimationFrame(render);
     if (mixer !== null) {
         //clock.getDelta()方法获得两帧的时间间隔
         // 更新播放器相关的时间
         mixer.update(clock.getDelta());
     }
 }
 render();