本章主要学习知识点
- 学习如何使用tweenjs创建动画
- 使用tweenjs实现相机运动动画
- 掌握如何实现相机飞行靠近观察设备
- 实现点击模型放大预览
tweenjs创建动画
Tween.js 创建动画主要是通过「补间动画」
自动计算属性变化的中间状态,让物体平滑过渡。
在tweenjs中我们只要告诉它物体当前状态和目标状态,它会自动帮我们计算中间过程
简单几步便可创建动画
初始化场景
包括mesh、camera、renderer等
const geometry = new THREE.SphereGeometry( 1, 32, 32 );
const material = new THREE.MeshBasicMaterial( { color: 'deeppink' } );
cube = new THREE.Mesh( geometry, material );
// 将网格添加到场景中
scene.add( cube );
创建动画对象
这里我们改变Mesh的位置、大小、颜色
const tween = new TWEEN.Tween(cube.position)
.to({x: 10, y: 10, z: 1}, 2000)
.start()
const tween2 = new TWEEN.Tween(cube.scale)
.to({x: 2, y: 2, z: 2}, 2000)
.start()
const tween3 = new TWEEN.Tween(cube.material.color)
.to({r: 1, g: .56, b: 0}, 2000)
.start()
动画刷新
renderer.render( scene, camera );
requestAnimationFrame( animate );
tween.update();
tween2.update();
tween3.update();
tweenjs相机运动动画
相机运动动画主要是让相机属性(如位置、视角)按设定轨迹平滑过渡。
下面是一个简单的示例
const tween = new TWEEN.Tween(camera.position)
.to({x: 10, y: 20, z: -16}, 3000)
.easing(TWEEN.Easing.Quadratic.InOut)
.onUpdate(() => {
camera.lookAt(0,0,0)
})
.start()
相机飞行靠近观察设备
通过补间动画让相机位置和视角平滑过渡到目标设备附近,已实现靠近观察设备
导入两个模型,一个电力控制器,一个人物模型
loader.load( 'model/electrical_box_-_free/scene.gltf', function ( gltf ) {
scene.add( gltf.scene );
eleModName = gltf.scene.name;
})
loader.load( 'model/stand_person/scene.gltf', function ( gltf2 ) {
scene.add( gltf2.scene );
gltf2.scene.position.set(5,-6,2)
gltf2.scene.scale.set(0.5,0.5,0.5)
personModName = gltf2.scene.name;
})
创建几个按钮,用来实现点击不同的按钮观察不同的模型
document.getElementById('A').addEventListener('click',function () {
const A = scene.getObjectByName(eleModName);
const pos = new THREE.Vector3()
A.getWorldPosition(pos);
const pos2 = pos.clone().set(0,0,4)
createCameraTween(pos2,controls.target)
})
document.getElementById('B').addEventListener('click',function () {
const B = scene.getObjectByName(personModName);
const pos = new THREE.Vector3()
B.getWorldPosition(pos);
const pos2 = pos.clone().set(7,-4,10)
createCameraTween(pos2,controls.target)
})
document.getElementById('C').addEventListener('click',function () {
const cameraPos = new THREE.Vector3(1,2,12)
createCameraTween(cameraPos,controls.target)
})
在查看效果之前,先来看下createCameraTween
该方法
function createCameraTween(endPos, endTarget) {
tween = new TWEEN.Tween({
x: camera.position.x,
y: camera.position.y,
z: camera.position.z,
// 相机开始指向的目标观察点
tx: controls.target.x,
ty: controls.target.y,
tz: controls.target.z
}).to({
x: endPos.x,
y: endPos.y,
z: endPos.z,
tx: endTarget.x,
ty: endTarget.y,
tz: endTarget.z
}, 1000).onUpdate(function (object) {
camera.position.set(object.x,object.y,object.z)
// camera.lookAt(object.tx,object.ty,object.tz)
controls.target.set(object.tx,object.ty,object.tz)
controls.update()
}).start();
}
这个函数用于创建动画,传入相机位置与控制器指向目标对象,当我们点击不同按钮时, 相机将平滑移动到指定观察位置
点击模型放大预览
要实现该效果其实也就是控制相机运动,只是加上了射线检测。
window.addEventListener('click', (event) => {
// 计算鼠标位置
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 更新射线
raycaster.setFromCamera(mouse, camera);
// 计算射线与模型的交点
const intersects = raycaster.intersectObjects(scene.children, true);
console.log(intersects);
if (intersects.length > 0) {
const object = intersects[0].object;
if(object.isMesh){
const pos = new THREE.Vector3();
object.getWorldPosition(pos);
const pos2 = pos.clone().addScalar(1);
createCameraTween(pos2, controls.target);
}
}
});