WEB 3D技术 three.js 补间动画(tween)

CSDN 2024-06-14 12:03:02 阅读 90

本文 我们来说 补间动画

比如说 我们有一个正方体 默认在如下图位置

在这里插入图片描述

然后 我们希望 一秒中之后 它到达如下图位置

在这里插入图片描述

那么 我们知道 终点和起点的位置 从起点到终点 一共需要一秒的时间

需要程序自己去处理这个图形 0.1 0.2 直到 1秒 它都分别要达到什么位置

通过开始和结束位置 补出中间的动画部分 这就叫补间动画

补间动画库 叫 tween 这个东西是可以单独安装的 但threeJs已经包含了

首先 我们要在代码中通过 threejs引入它

//导入tween 补间动画import { Tween } from "three/examples/jsm/libs/tween.module.js";

我们可以这样写

import './style.css'import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";//导入tween 补间动画import { Tween } from "three/examples/jsm/libs/tween.module.js";//创建相机const camera = new THREE.PerspectiveCamera( 45, //视角 视角越大 能看到的范围就越大 window.innerWidth / window.innerHeight,//相机的宽高比 一般和画布一样大最好 0.1, //近平面 相机能看到最近的距离 1000 //远平面 相机能看到最远的距离);const scene = new THREE.Scene();const sphere1 =new THREE .Mesh( new THREE.SphereGeometry(1, 32, 32), new THREE.MeshBasicMaterial({ color: 0x00FF00 }))sphere1.position.x = -2;scene.add(sphere1);//创建Tween 补间动画效果const tween = new Tween(sphere1.position);tween.to({ x: 4},1000)//c创建一个canvas容器 并追加到 body上const renderer = new THREE.WebGLRenderer(0);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);//设置相机位置 这里 我们设置Z轴 大家可以试试 S Y 和 Z 都是可以的camera.position.z = 5;//设置相机默认看向哪里 三个 0 代表 默认看向原点camera.lookAt(0, 0, 0);//将内容渲染到元素上renderer.render(scene, camera);const controls = new OrbitControls(camera, renderer.domElement);function animate() { controls.update(); requestAnimationFrame(animate); /*cube.rotation.x += 0.01; cube.rotation.y += 0.01;*/ renderer.render(scene, camera);}animate();

我们new 出一个 Tween 对象 他的两个参数 一个是 sphere1 我们写的一个圆形几何体 就要用它动画 然后 position 告诉它动画操作 position字段

然后 修饰动画 to 两个参数 第一个告诉它 我们要改什么 动画 x轴最终变成4 第二个参数告诉它用时 我们这里 1000 一千毫秒 就是一秒

当然 管这样设置不够

我们还得让它动起来

在这里插入图片描述

然后 我们可以在它下面写

tween.start();

动画对象的 start用于启动命令

但光这样 依旧不够

我们还需要一点一点的监听它更新

在这里插入图片描述

然后 我们运行代码

这个动画就跑起来了

在这里插入图片描述

如果说 我们不是只想执行一次 而是希望它多重复几次

在这里插入图片描述

tween.repeat 设置动画重复

参数传入 Infinity 代表重复无限次

想循环指定次数 直接传数值就OK了

例如 我这里想重复两次 就直接传2

在这里插入图片描述

然后 它每一次的动画效果 我们也是可以事件监听的

我们将 tween.to 的代码改成这样

tween.to({ x: 4},1000).onUpdate(() => { console.log(sphere1.position.x);})

我们 onUpdate 监听动画变动

然后用 console.log 在每次触发 输出 sphere1.position.x的值

运行结果如下

在这里插入图片描述

我们还可以设置它循环往复

就是 过去了只有 在原路返回 而不是直接一闪 就回到原位了

他的函数名叫 yoyo

在这里插入图片描述

这样动画来回就会看着自然很多

delay 方法能够设置 延迟多久之后执行动画

这里我设置了 三秒之后执行

在这里插入图片描述

在日程 我们物体移动 也存在加速 例如 一个赛车起步比较慢 跑着跑着就快了

还有 动物 跑到后面累了 越来越慢

都是可以的

但是 我们目前这个物体动画是一个平均速度的

具体 如下图 可以设置这些类型

在这里插入图片描述

我们可以先用 Quadratic.InOut 先加速 然后慢慢的减速效果

我们先要把引入tween.module.js的代码改一下

import TWEEN,{ Tween } from "three/examples/jsm/libs/tween.module.js";

我们需要整改TWEEN对象

然后 加上如下代码

tween.easing(TWEEN.Easing.Quadratic.InOut);

在这里插入图片描述

后面的 Quadratic.InOut 大家可以根据自己的需要调整

在这里插入图片描述

再次运行代码 就会有一个慢慢加速 然后 减速的过程了

在这里插入图片描述

还有一个点 就动画连接

比如 我们希望它横向走的x的某个点 然后往下走

将两个动画一气呵成

这里 我们 先将 循环往复 执行多少次 延迟 都注释掉

在这里插入图片描述

我们先在下面 再创建一个动画

const tween2 = new Tween(sphere1.position);tween2.to({ y: -4},1000)

对象和属性参数和第一个动画是一样的

然后 改 y轴 结束到 -4的位置

然后 我们将代码改成

import './style.css'import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";//导入tween 补间动画import TWEEN,{ Tween } from "three/examples/jsm/libs/tween.module.js";//创建相机const camera = new THREE.PerspectiveCamera( 45, //视角 视角越大 能看到的范围就越大 window.innerWidth / window.innerHeight,//相机的宽高比 一般和画布一样大最好 0.1, //近平面 相机能看到最近的距离 1000 //远平面 相机能看到最远的距离);const scene = new THREE.Scene();const sphere1 =new THREE .Mesh( new THREE.SphereGeometry(1, 32, 32), new THREE.MeshBasicMaterial({ color: 0x00FF00 }))sphere1.position.x = -2;scene.add(sphere1);//创建Tween 补间动画效果const tween = new Tween(sphere1.position);tween.to({ x: 4},1000).onUpdate(() => { console.log(sphere1.position.x);})//tween.yoyo(true);//tween.repeat(2);//tween.delay(3000);tween.easing(TWEEN.Easing.Quadratic.InOut);const tween2 = new Tween(sphere1.position);tween2.to({ y: -4},1000)tween.chain(tween2);tween.start();//c创建一个canvas容器 并追加到 body上const renderer = new THREE.WebGLRenderer(0);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);//设置相机位置 这里 我们设置Z轴 大家可以试试 S Y 和 Z 都是可以的camera.position.z = 5;//设置相机默认看向哪里 三个 0 代表 默认看向原点camera.lookAt(0, 0, 0);//将内容渲染到元素上renderer.render(scene, camera);const controls = new OrbitControls(camera, renderer.domElement);function animate() { controls.update(); TWEEN.update(); requestAnimationFrame(animate); /*cube.rotation.x += 0.01; cube.rotation.y += 0.01;*/ renderer.render(scene, camera);}animate();

因为 如果要监听动画对象的 update 你两个都要监听 所以 我们直接监听 TWEEN.update就可以了

然后 用chain将 y动画加到第一个动画里面来

然后启动tween.start

我们运行代码

这样 我们就可以看到 x移动结束后 他又开始执行y轴的了

在这里插入图片描述

其实 除了onUpdate

我们的监听函数还非常多

例如

tween.onStart(()=>{ console.log("动画已开始");})tween.onComplete(()=>{ console.log("动画已完成");})tween.onStop(()=>{ console.log("动画已被暂停");})tween.onUpdate(()=>{ console.log("动画已更新");})

tween.stop(); 即可暂停动画的执行

暂停之后 执行 tween.start(); 即可再次启动动画



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。