ThreeJS中的动画
动画类型
动画类型 | 描述 |
---|---|
帧动画 (Frame Animation) | 将一系列图片按照顺序播放,形成动画效果,类似于传统手绘动画。 |
逐帧动画 (Sprite Animation) | 通过改变精灵纹理的位置或贴图来模拟运动,常用于游戏中的人物、道具等的动画效果。 |
骨骼动画 (Skeletal Animation) | 通过骨骼的动画变化来模拟角色的运动,将角色的形态分解成多个骨骼,并通过调整骨骼的变换来实现动画效果。 |
形状关键帧动画 (Morph Target Animation) | 通过调整网格顶点的位置、法线和颜色等属性,来模拟物体的形变和运动,比如角色的面部表情、物体的形变等。 |
粒子动画 (Particle Animation) | 通过控制一组小粒子的运动轨迹、大小、透明度等属性,来模拟各种自然现象,比如烟雾、火花、雨滴等。 |
基于物理引擎的动画 (Physics-based Animation) | 通过物理引擎模拟物体的运动、碰撞、重力、弹性等物理特性,来实现更加真实的动画效果,常用于游戏中的角色、物体等。 |
ThreeJS 中的动画类
AnimationMixer
- 使用格式:
const mixer = new AnimationMixer( object : Object3D )
- 功能:管理和混合场景中的动画数据。
- 参数说明:
object
:要添加动画数据的Object3D
对象。
- 示例:
const mixer = new THREE.AnimationMixer(mesh);
- 使用格式:
AnimationClip
- 使用格式:
AnimationClip( name : String, duration : Number, tracks : Array )
- 功能:表示一个包含一组
AnimationTrack
的动画片段。 - 参数说明:
name
:动画片段的名称。duration
:动画片段的持续时间(秒)。tracks
:包含AnimationTrack
对象的数组。
- 示例:
const clip = THREE.AnimationClip.CreateFromMorphTargetSequence( "morph", geometry.morphAttributes.position, 30 );
- 使用格式:
AnimationAction
- 使用格式:
AnimationAction( mixer : AnimationMixer, clip : AnimationClip, localRoot : Object3D )
- 功能:表示一个
AnimationClip
在AnimationMixer
中的播放实例。 - 参数说明:
mixer
:AnimationMixer
对象。clip
:AnimationClip
对象。localRoot
:本地根对象,动画中的对象将相对于此对象移动。
- 示例:
const action = mixer.clipAction(clip);
- 使用格式:
AnimationObjectGroup
- 使用格式:
AnimationObjectGroup( ...objects : Object3D[] )
- 功能:管理多个对象的动画。
- 参数说明:
objects
:要添加到AnimationObjectGroup
的Object3D
对象。
- 示例:
const group = new THREE.AnimationObjectGroup(mesh1, mesh2); const clip = THREE.AnimationClip.CreateFromAction(animationAction); clip.tracks.shift(); // 移除第一条跟踪轨迹 group.clipAction(clip).play(); // 播放动画
- 使用格式:
KeyframeTrack
- 使用格式:
KeyframeTrack( name : String, times : Array, values : Array, interpolation : InterpolationModes )
- 功能:表示动画的关键帧序列。
- 参数说明:
name
:关键帧序列的名称。times
:关键帧时间的数组。values
:与关键帧相关联的值的数组。interpolation
:插值模式,默认为THREE.InterpolateLinear
。
- 示例:
const times = [0, 1, 2]; const values = [0, 1, 0]; const track = new THREE.NumberKeyframeTrack(".opacity", times, values);
- 使用格式:
动画的运行是通过 AnimationMixer 类实现的。当一个模型需要播放动画时,我们需要将模型的动画剪辑(AnimationClip)添加到 AnimationMixer 实例中,然后通过 mixer.clipAction() 方法获取一个动画动作(AnimationAction)实例,调用 play() 方法播放动画,AnimationAction 的更新又通过 AnimationMixer.update() 方法实现。
- 创建动画剪辑(AnimationClip),并将其包含的动画轨迹(AnimationTrack)绑定到场景中的对象上。
- 创建动画混合器(AnimationMixer),并将动画剪辑添加到混合器中。
- 调用混合器的 update 方法,更新当前时间下各个对象的状态。
- 将更新后的状态应用到场景中的对象上,使动画动起来。
// 使用GLTFLoader加载模型
loader.load("models/gltf/Soldier.glb", function (gltf) {
// 获取模型
model = gltf.scene;
// 将模型添加到场景中
scene.add(model);
// 遍历模型内的所有对象
model.traverse(function (object) {
// 如果对象是网格,则开启阴影投射
if (object.isMesh) object.castShadow = true;
});
// 创建骨骼辅助对象,用于调试和查看骨骼结构
skeleton = new THREE.SkeletonHelper(model);
// 设置骨骼辅助对象为不可见
skeleton.visible = false;
// 将骨骼辅助对象添加到场景中
scene.add(skeleton);
// 创建面板
createPanel();
// 获取模型的动画数组
const animations = gltf.animations;
// 创建动画混合器
mixer = new THREE.AnimationMixer(model);
// 获取模型的不同动作,并将其加入动画混合器中
idleAction = mixer.clipAction(animations[0]);
walkAction = mixer.clipAction(animations[3]);
runAction = mixer.clipAction(animations[1]);
// 将不同动作保存在数组中
actions = [idleAction, walkAction, runAction];
// 激活所有动作
activateAllActions();
// 调用动画循环函数
animate();
});
function activateAllActions() {
setWeight(idleAction, settings["modify idle weight"]);
setWeight(walkAction, settings["modify walk weight"]);
setWeight(runAction, settings["modify run weight"]);
actions.forEach(function (action) {
action.play();
});
}
function setWeight(action, weight) {
// 设置动画的权重值
action.enabled = true; // 启用当前动画
action.setEffectiveTimeScale(1); // 设置动画播放速度为正常速度
action.setEffectiveWeight(weight); // 设置动画权重值
}
function animation(){
let mixerUpdateDelta = clock.getDelta();
mixer.update( mixerUpdateDelta );
}
Powered by Waline v2.13.0