threejs 动画系统
阅读数:96 评论数:0
跳转到新版页面分类
html/css/js
正文
一、动画片段 animation clips
每个animationClip通常保存3D动画对象某个活动的数据。举个例子,假如mesh是一个角色,可能有一个AnimationClip实现步行循环,第二个AnimationClip实现跳跃,第三个AnimationClip实现闪避等等。
THREE.AnimationClip
是 Three.js 中的动画数据容器,定义了动画的内容和行为。它描述了动画如何随时间变化,包含关键帧数据(如位置、旋转、缩放或骨骼动画)。AnimationClip
是动画系统的核心组件之一,与 THREE.AnimationMixer
一起使用,用于实现 3D 对象的动画效果。
1、关键属性
(1)name
动画的名称,用于标识和管理动画。
(2)duration
- 动画的总时长,单位为秒。
- 如果未显式设置,会根据最长的关键帧时间自动计算。
(3)tracks
包含动画的关键帧轨道(KeyframeTrack
)数组,每个轨道控制一个属性
2、常用方法
(1)THREE.AnimationClip.findByName(clips, name)
在动画剪辑数组中查找指定名称的动画剪辑。
(2)THREE.AnimationClip.createFromMorphTargetSequence(name, morphTarget, fps, noLoop)
从形态目标序列创建动画剪辑,通常用于形变动画。
(3)THREE.AnimationClip.parse(json)
从 JSON 数据解析动画剪辑。
(4)THREE.AnimationClip.toJSON()
将动画剪辑转换为 JSON 格式。
3、使用加far动画剪辑
如果加载了包含动画的 3D 模型(例如 GLTF 文件),可以直接使用动画剪辑:
const loader = new THREE.GLTFLoader();
loader.load('path/to/model.gltf', (gltf) => {
const model = gltf.scene;
const animations = gltf.animations; // 加载的动画剪辑数组
scene.add(model);
// 创建 AnimationMixer
const mixer = new THREE.AnimationMixer(model);
// 播放指定的动画剪辑
const clip = THREE.AnimationClip.findByName(animations, 'run');
const action = mixer.clipAction(clip);
action.play();
// 渲染循环
const clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta();
mixer.update(delta);
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
});
4、示例
// 创建关键帧轨道
const positionKF = new THREE.VectorKeyframeTrack(
'.position', // 属性路径(对象的位置)
[0, 1, 2], // 时间点(单位:秒)
[0, 0, 0, 1, 1, 1, 2, 0, 0] // 位置值序列
);
const rotationKF = new THREE.QuaternionKeyframeTrack(
'.quaternion', // 属性路径(对象的旋转)
[0, 1, 2], // 时间点
[0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1] // 四元数值序列
);
// 创建动画剪辑
const clip = new THREE.AnimationClip('moveAndRotate', 2, [positionKF, rotationKF]);
// 将动画剪辑应用到对象
const mixer = new THREE.AnimationMixer(object);
const action = mixer.clipAction(clip);
action.play();
// 渲染循环中更新动画
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
animate();
二、关键帧轨道 Keyframe Tracks
在一个AnimationClip里面,每个动画属性的数据都存储在一个单独的KeyframeTrack中。
三、动画混合器 Animation Mixer
存储的数据仅构成动画的基础,实际播放由AnimationMixer控制。
1、THREE.AnimationMixer关键方法
THREE.AnimationMixer
是 Three.js 动画系统的核心组件,主要用于控制和管理 3D 对象的动画播放。它提供了一套灵活的 API,可以实现动画的播放、暂停、停止、过渡以及混合,是动画系统中的 "播放器"。
可以绑定到一个 THREE.Mesh
、THREE.Group
或 THREE.AnimationObjectGroup
,从而控制单个对象或一组对象的动画。
关键方法
(1)clipAction(animationClip)
获取或创建一个 AnimationAction
,用于管理指定动画剪辑的播放状态。
const action = mixer.clipAction(animationClip);
action.play();
(2)update(deltaTime)
更新动画的播放进度,通常在渲染循环中调用。
const delta = clock.getDelta();
mixer.update(delta);
(3)stopAllAction()
停止所有正在播放的动画。
(4)setTime(time)
手动设置动画的播放时间。
(5)uncacheClip(animationClip)
从 AnimationMixer
中移除指定的动画剪辑。
2、示例代码
// 加载模型和动画
const loader = new THREE.GLTFLoader();
loader.load('path/to/model.gltf', (gltf) => {
const model = gltf.scene;
const animations = gltf.animations; // 包含动画剪辑的数组
scene.add(model);
// 创建 AnimationMixer
const mixer = new THREE.AnimationMixer(model);
// 获取并播放第一个动画剪辑
const action = mixer.clipAction(animations[0]);
action.play();
// 创建一个时钟
const clock = new THREE.Clock();
// 渲染循环
function animate() {
requestAnimationFrame(animate);
// 更新动画
const delta = clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
animate();
});
四、动画行为 Animation Actions
Animation Actions本身只有很少的属性和方法,因为它可以通过AnimationActions来控制,通过配置AnimationAction,可以决定何时播放、暂停或停止其中一个混合器的某个AnimationClip,这个AnimationClip是否需要重复播放以及重复的频率,是否需要使用淡入淡出或时间缩放等。
注间:并非所有模型格式都包含动画(尤其是OBJ,没有),而且只有某些three.js加载器支持AnimationClip序列。以下几个加载器支持动画:
1、ObjectLoader
2、BVHLoader
3、ColladaLoader
4、FBXLoader
5、GLTFLoader
6、MMDLoader
7、SEA3DLoader
另外,3ds max和maya当前无法直接导出多个动画到一个文件中(这意味着动画不是在同一时间线上)。
示例
var mesh;
// 新建一个AnimationMixer, 并取得AnimationClip实例列表
var mixer = new THREE.AnimationMixer( mesh );
var clips = mesh.animations;
// 在每一帧中更新mixer
function update () {
mixer.update( deltaSeconds );
}
// 播放一个特定的动画
var clip = THREE.AnimationClip.findByName( clips, 'dance' );
var action = mixer.clipAction( clip );
action.play();
// 播放所有动画
clips.forEach( function ( clip ) {
mixer.clipAction( clip ).play();
} );
五、调整动画速度
1、调整整体速度
mixer.timeScale
是一个数值,控制AnimationMixer
中所有动画的播放速度。- 默认值为
1
,表示正常速度。 - 例如:
- 值为
0.5
:动画以一半的速度播放(减慢)。 - 值为
2
:动画以两倍的速度播放(加速)。 - 值为
-1
:动画以相反方向播放(倒播)。
- 值为
// 创建动画混合器
const mixer = new THREE.AnimationMixer(model);
// 加载动画剪辑
const action = mixer.clipAction(animationClip);
// 设置全局动画速度
mixer.timeScale = 0.5; // 将动画速度减慢一半
// 播放动画
action.play();
2、针对特定动画设置速度
如果只需要调整某个特定动画的速度,可以直接设置该动画的 timeScale
属性。
// 创建动画混合器
const mixer = new THREE.AnimationMixer(model);
// 加载动画剪辑
const action = mixer.clipAction(animationClip);
// 设置特定动画的播放速度
action.timeScale = 2; // 使该动画以两倍速度播放
// 播放动画
action.play();
3、通过更改AnimationMixer的时间
如果需要更加精细地控制动画速度,可以在渲染循环中手动更新动画混合器的时间。通过修改传递给 mixer.update(delta)
的 delta
值实现。
let clock = new THREE.Clock();
// 渲染循环
function animate() {
requestAnimationFrame(animate);
// 获取时间增量
const delta = clock.getDelta();
// 手动控制动画速度(例如减慢一半)
mixer.update(delta * 0.5); // 0.5 是自定义速度因子
renderer.render(scene, camera);
}
animate();