Lazy loaded image
🕋ThreeJS — KeyFrameAnimation & Bone
字数 1304阅读时长≈ 4 分钟
2023-8-3
2023-8-3
4
type
status
date
slug
summary
tags
category
icon
password
Edited
Aug 3, 2023 08:18 AM
Created
Aug 3, 2023 07:58 AM

KeyFrameAnimation

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

使用步骤

  1. 模型命名
  1. KeyframeTrack设置关键帧数据
  1. 创建关键帧动画AnimationClip
  1. AnimationMixer播放关键帧动画
  1. mixer.update()更新播放器AnimationMixer时间
// 1 // 给需要设置关键帧动画的模型命名 mesh.name = "Box"; // 2 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]); // 3 // 基于关键帧数据,创建一个clip关键帧动画对象,命名"test",持续时间6秒。 const clip = new THREE.AnimationClip("test", 6, [posKF, colorKF]); // 4 //AnimationMixer的`.clipAction()`返回一个AnimationAction对象 const clipAction = mixer.clipAction(clip); //.play()控制动画播放,默认循环播放 clipAction.play(); // 5 const clock = new THREE.Clock(); function loop() { const frameT = clock.getDelta(); // 更新播放器相关的时间 mixer.update(frameT); requestAnimationFrame(loop); } loop();

动画动作对象AnimationAction 属性

  • 循环属性.loop
    • 控制动画是否循环播放
  • .clampWhenFinished属性
    • 模型停留在关键帧动画结束的状态
  • .play()
    • 播放
  • .stop()
    • 停止结束动画
  • .paused
    • 是否暂停播放
  • .timeScale
    • 倍速播放
  • .time
    • 开始播放时间
  • .duration
    • 播放结束时间
 

动画停留在任意时间

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

外部模型

如果一个模型中存在动画,可以通过属性获取 gltf.animations
gltf.animations是一个数组,如果没有帧动画数据,就是一个空数组,有帧动画数据的情况下,里面可能1个或多个Clip动画对象AnimationClip
 

变形动画

  • .morphAttributes设置几何体变形目标顶点数据
  • .morphTargetInfluences权重系数控制变形程度
mesh的几何体变形目标是放在一个数组.morphAttributes.position中的,设置权重系数morphTargetInfluences的时候,需要设置索引值, 比如.morphTargetInfluences[0]影响的变形目标是.morphAttributes.position[0].morphTargetInfluences[1]影响的变形目标是.morphAttributes.position[1]

使用

const geometry2 = new THREE.BoxGeometry(50, 50, 50) // 为geometry提供变形目标的顶点数据(注意和原始geometry顶点数量一致) const target1 = new THREE.BoxGeometry(50, 200, 50).attributes.position //变高 const target2 = new THREE.BoxGeometry(10, 50, 10).attributes.position //变细 // 注意:给一个几何体geometry设置顶点变形数据.morphAttributes时候要注意,在执行代码new THREE.Mesh()之前设置,否则报错。 // 几何体顶点变形目标数据,可以设置1组或多组 geometry2.morphAttributes.position = [target1, target2] const mesh2 = new THREE.Mesh(geometry2, material1) //权重0.5:物体形状对应geometry和target1变形中间状态 mesh2.morphTargetInfluences[0] = 0.5 mesh2.morphTargetInfluences[1] = 0.5 mesh2.name = 'Mesh2' scene.add(mesh2) const KF1 = new THREE.KeyframeTrack('Mesh2.morphTargetInfluences[0]', [0, 5], [0, 1]) const KF2 = new THREE.KeyframeTrack('Mesh2.morphTargetInfluences[1]', [5, 10], [0, 1]) const clip2 = new THREE.AnimationClip('t', 10, [KF1, KF2]) // 播放变形动画 const mixer2 = new THREE.AnimationMixer(mesh2) const clipAction2 = mixer2.clipAction(clip2) clipAction2.play() function loop() { requestAnimationFrame(loop); const frameT = clock.getDelta(); // 更新播放器相关的时间 mixer.update(frameT); } loop();
 

Bone

骨骼关节Bone的作用就是模拟人或动物的关节运动,控制身体表面变形,来生成骨骼动画

骨骼关节Bone树结构

人或动物实际的骨骼关节结构往往是比较复杂的,一般可以用一个层级树结构表达。
const Bone1 = new THREE.Bone(); //关节1,用来作为根关节 const Bone2 = new THREE.Bone(); //关节2 const Bone3 = new THREE.Bone(); //关节3 // 设置关节父子关系 多个骨头关节构成一个树结构 Bone1.add(Bone2); Bone2.add(Bone3); //根关节Bone1默认位置是(0,0,0) Bone2.position.y = 60; //Bone2相对父对象Bone1位置 Bone3.position.y = 30; //Bone3相对父对象Bone2位置 //平移Bone1,Bone2、Bone3跟着平移 Bone1.position.set(50,0,50); // 骨骼关节旋转 Bone1.rotateX(Math.PI / 6); Bone2.rotateX(Math.PI / 6); // 骨骼关节可以和普通网格模型一样作为其他模型子对象,添加到场景中 const group = new THREE.Group(); group.add(Bone1);
 

SkeletonHelper可视化骨骼关节

把所有骨骼关节对象的父对象,也就是根节点骨骼Bone1,添加一个模型对象中作为子对象,然后把模型对象作为SkeletonHelper的参数,就可以看到骨骼关节的可视化效果。
// SkeletonHelper会可视化参数模型对象所包含的所有骨骼关节 const skeletonHelper = new THREE.SkeletonHelper(group); group.add(skeletonHelper);
 
这次的内容都是和动画相关的,如果了解过CSS的话,非常好理解
内容差不多到这里就介绍完了 🎉🎉🎉
 

参考链接

  1. Three.js中文网 (webgl3d.cn)
上一篇
在 Deno 中 使用 npm 包
下一篇
ThreeJS — 通过 Ray & Label 来做一个点击物体高亮并提示信息

评论
Loading...