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.MeshTHREE.GroupTHREE.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();

 




相关推荐