ThreeJS教程:关键帧动画

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

关键帧动画

打开课件案例源码,你可以看到物体从一个位置移动到另一个位置的动画效果,移动过程中也出现过颜色变化。

课件源码效果具体描述,就是0~3秒物体逐渐从坐标原点移动端x轴100位置,然后3~6秒物体逐渐从x轴100移动到z轴100位置,同时2~5秒时间内,把物体从红色逐渐改变为蓝色

关键帧动画解释

所谓关键帧动画,你可以理解为在时间轴上,选择几个关键的时间点,然后分别定义这几个时间点对应物体状态(比如位置、姿态、颜色等),然后基于几个关键的时间——状态数据,生成连续的动画。

课件源码位置关键帧数据(时间——状态)

  • 0秒:坐标原点
  • 3秒:x轴上100坐标
  • 6秒:z轴上100坐标

课件源码颜色关键帧数据(时间——状态)

  • 2秒:红色
  • 5秒:蓝色

1. 创建关键帧动画AnimationClip

  • 1.1 给需要设置关键帧动画的模型命名
  • 1.2 设置关键帧数据KeyframeTrack
  • 1.3 基于关键帧数据KeyframeTrack,创建关键帧动画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", 9, [posKF, colorKF]);

1.1 模型命名

你如果你想给一个模型对象设置关键帧动画,比如一个网格模型mesh、一个层级模型group,模型需要有一个名字,没有的话,可以通过.name属性命名。

mesh.name = "Box";

1.2 KeyframeTrack设置关键帧数据

KeyframeTrack参数1是一个字符串,字符串内容是模型对象的名字.属性构成,比如Box.position表示模型位置,比如Box.material.color表示模型颜色,参数2是时间轴上取的几个关键帧时间点,参数3是时间点对应的物体状态。

位置关键帧数据(时间——状态)

  • 0秒:坐标原点
  • 3秒:x轴上100坐标
  • 6秒:z轴上100坐标
// 给名为Box的模型对象的设置关键帧数据KeyframeTrack
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秒:蓝色
// 从2秒到5秒,物体从红色逐渐变化为蓝色
const colorKF = new THREE.KeyframeTrack('Box.material.color', [2, 5], [1, 0, 0, 0, 0, 1]);

1.3 创建关键帧动画AnimationClip

基于关键帧数据KeyframeTrack,创建关键帧动画AnimationClip,这样就可以利用关键帧里面的数据生成一个关键帧动画,用于接下来的动画播放。

下面代码基于关键帧数据posKF、colorKF,创建一个clip关键帧动画对象AnimationClip,命名为test,动画持续时间6秒。

// 1.3 AnimationClip表示一个关键帧动画,可以基于关键帧数据产生动画效果
// 创建一个clip关键帧动画对象,命名"test",动画持续时间6s
// AnimationClip包含的所有关键帧数据都放到参数3数组中即可
const clip = new THREE.AnimationClip("test",6,[posKF, colorKF]);

2.1 AnimationMixer播放关键帧动画AnimationClip

前面代码,已经编辑好一个模型mesh的关键帧动画AnimationClip,如果你想播放动画,就要借助播放器AnimationMixer

//包含关键帧动画的模型对象作为AnimationMixer的参数创建一个播放器mixer
const mixer = new THREE.AnimationMixer(mesh);

执行播放器AnimationMixer.clipAction()方法返回一个AnimationAction对象,AnimationAction对象用来控制如何播放,比如.play()方法。

//AnimationMixer的`.clipAction()`返回一个AnimationAction对象
const clipAction = mixer.clipAction(clip); 
//.play()控制动画播放,默认循环播放
clipAction.play(); 

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

如果想播放动画开始变化,需要周期性执行mixer.update()更新播放器AnimationMixer时间数据,比如你可以在requestAnimationFrame创建的可以周期性执行的函数中,更新播放器时间数据。

function loop() {
    requestAnimationFrame(loop);
}
loop();

通过Clock对象辅助获取每次loop()执行的时间间隔。

const clock = new THREE.Clock();
function loop() {
    requestAnimationFrame(loop);
    //clock.getDelta()方法获得loop()两次执行时间间隔
    const frameT = clock.getDelta();
}
loop();

执行mixer.update()更新播放器AnimationMixer时间数据

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

如果你不想用requestAnimationFrame重新创建一个循环执行函数,也可以在index.js文件渲染循环中引入mixer.update()的代码

上一篇:ThreeJS教程:Sprite标签(Canvas作为贴图) (mvrlink.com)

下一篇:ThreeJS教程:动画播放(暂停、倍速、循环) (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号