Three.js-硬要自学系列28 (tweenjs创建动画、相机运动动画、相机飞行、模型放大预览)

312 阅读2分钟

本章主要学习知识点

  • 学习如何使用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();

213.gif

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()

2.gif

相机飞行靠近观察设备

通过补间动画让相机位置和视角平滑过渡到目标设备附近,已实现靠近观察设备

导入两个模型,一个电力控制器,一个人物模型

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;
})

image.png

创建几个按钮,用来实现点击不同的按钮观察不同的模型

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();
}

这个函数用于创建动画,传入相机位置与控制器指向目标对象,当我们点击不同按钮时, 相机将平滑移动到指定观察位置

423.gif

点击模型放大预览

要实现该效果其实也就是控制相机运动,只是加上了射线检测。

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);
        } 
    }
});

4235.gif

以上案例均可在案例中心查看体验

THREE 案例中心

image.png