关键帧动画
创建关键帧动画
// 时间数组
const timeArr = [0, 3, 6, 9];
// 位置数组,3组为一个位置
const positionArr = [0, 0, 0, 100, 0, 0, 0, 0, 100, 0, 0, 0];
// 创建位置关键帧
const posKF = new THREE.KeyframeTrack('Box.position', timeArr, positionArr);
// 创建颜色关键帧
const colorKF = new THREE.KeyframeTrack('Box.material.color', [0, 3, 6, 9], [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]);
// 创建动画
const clip = new THREE.AnimationClip('test', 9, [posKF, colorKF]);
// 创建动画播放器AnimationMixer,设置要播放的物体为mesh
const mixer = new THREE.AnimationMixer(mesh);
// 定义播放器所播放的动画
const clipAction = mixer.clipAction(clip);
// 开始播放动画,play默认为循环播放
clipAction.play();
// 创建时钟对象
const clock = new THREE.Clock();
function loop () {
requestAnimationFrame(loop);
// 获取loop()执行间隔时间
const frameT = clock.getDelta();
// 更新播放器时间数据
mixer.update(frameT);
}
loop();
关键帧动画(暂停、倍速、循环)
执行动画播放器AnimationMixer的clipAction()方法会返回一个AnimationAction对象。AnimationAction对象的功能就是用来控制如何播放关键帧动画,比如是否播放、几倍速播放、是否循环播放、是否暂停播放等等
// 设置动画不循环播放
clipAction.loop = THREE.LoopOnce;
// 设置物体状态停留在动画结束的时候(默认情况下物体状态会停留在动画播放前)
clipAction.clampWhenFinished = true;
// 设置动画停止结束,回到开始状态
clipAction.stop();
// 设置动画为暂停播放状态
clipAction.paused = true;
// 设置动画2倍速播放
clipAction.timeScale = 2;
// 通过GUI对象动态调节播放倍速
const gui = new GUI(); //创建GUI对象
gui.add(clipAction, 'timeScale', 0, 6); // 0~6倍速之间调节
动画播放(任意时间播放状态)
// 设置开始播放时间
clipAction.time = 1;
// 设置播放结束时间
clipAction.duration = 5;
// 设置拖动条控制播放动画
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
const gui = new GUI(); //创建GUI对象
gui.add(clipAction, 'time', 0, 6);
gui.add(clipAction, 'time', 0, 6).step(0.1);
解析外部模型关键帧动画
在开发过程中,有时候会用三维建模软件设置动画,一起跟随模型导出文件,这时候,只需要播放文件中的动画即可
loader.load("../士兵.glb", function (gltf) {
// console.log('动画数据', gltf.animations);
model.add(gltf.scene);
// 创建动画播放器
const mixer = new THREE.AnimationMixer(gltf.scene);
// 添加文件中的动画
const clipAction = mixer.clipAction(gltf.animations[3]);
// 开始播放
clipAction.play();
const clock = new THREE.Clock();
function loop () {
requestAnimationFrame(loop);
//clock.getDelta()方法获得loop()两次执行时间间隔
const frameT = clock.getDelta();
// 更新播放器相关的时间
mixer.update(frameT);
}
loop();
})
变形动画
使用BufferGeometry的morphAttributes属性设置几何体目标顶点变形数据,Mesh的morphTargetInfluences属性控制变形的权重系数
const geometry = new THREE.BoxGeometry(50, 50, 50);
const target1 = new THREE.BoxGeometry(50, 200, 50).attributes.position;
const target2 = new THREE.BoxGeometry(10, 50, 10).attributes.position;
// 设置morphAttributes变形属性为target1和target2
geometry.morphAttributes.position = [target1, target2]
const material = new THREE.MeshLambertMaterial({
color: 0x00ffff
});
const mesh = new THREE.Mesh(geometry, material);
mesh.name = 'Box';
// 将变形属性创建成关键帧动画
const KF1 = new THREE.KeyframeTrack('Box.morphTargetInfluences[0]', [0, 5], [0, 1]);
const KF2 = new THREE.KeyframeTrack('Box.morphTargetInfluences[1]', [5, 10], [0, 1]);
const clip = new THREE.AnimationClip("test", 10, [KF1, KF2]);
// 播放变形动画
const mixer = new THREE.AnimationMixer(mesh);
const clipAction = mixer.clipAction(clip);
clipAction.play();
clipAction.loop = THREE.LoopOnce; //不循环播放
clipAction.clampWhenFinished = true // 物体状态停留在动画结束的时候
const clock = new THREE.Clock();
function loop () {
requestAnimationFrame(loop);
const frameT = clock.getDelta();
// 更新播放器时间
mixer.update(frameT);
}
loop();
export default mesh;
初始骨骼Bone
Bone骨骼是threejs的一个类,用来模拟人或动物的骨骼,他的父节点是Object3D,继承了位置属性position、旋转属性rotation等等
// 创建骨骼
const Bone1 = new THREE.Bone();
const Bone2 = new THREE.Bone();
const Bone3 = new THREE.Bone();
// 设置骨骼父子关系,将骨骼关联起来
Bone1.add(Bone2);
Bone2.add(Bone3);
Bone1.position.set(50, 0, 50);
Bone2.position.y = 60;
Bone3.position.y = 30;
// 将骨骼添加至组对象中
const group = new THREE.Group();
group.add(Bone1);
// 创建骨骼处理器,显示我们创建的骨骼对象
const SkeletonHelper = new THREE.SkeletonHelper(group);
group.add(SkeletonHelper);
// GUI动态控制骨骼旋转
const gui = new GUI();
gui.add(Bone1.rotation, 'x', 0, Math.PI / 2).name('骨骼1');
gui.add(Bone2.rotation, 'x', 0, Math.PI / 2).name('骨骼2');