Tween.js在Three.js中的应用:为3D动画添加流畅过渡

前言

Web开发领域,Three.js已经成为构建精彩3D内容的首选库之一。它让开发者能够轻松地在浏览器中创建和展示复杂的3D场景。然而,要让这些场景栩栩如生,平滑的动画效果是必不可少的。这就引入了Tween.js——一个轻量级但功能强大的JavaScript库,专门用于在Web应用中创建平滑的补间动画。本文将探讨如何在Three.js项目中集成并利用Tween.js来增强3D对象的动画表现。

简介

Tween.js 是一个简单易用的库,专注于数值的平滑插值(interpolation),非常适合于实现动画效果。无论是简单的颜色渐变、对象位置移动,还是复杂的序列动画,Tween.js都能轻松应对。在与Three.js结合时,它能显著提升3D场景的互动性和视觉吸引力。

安装Tween.js

官方地址为:https://github.com/tweenjs/tween.js

npm install tween.js

当然three.js包中自带的包含tween.js,其中three.js得tween地址为:node_moduls>three>examples>jsm>libs>tween.module.js

导入补间动画

import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'

tween.js的核心方法

.to()方法

        控制补间的运动形式及方向.to(), 当tween启动时,Tween.js将读取当前属性值并 应用相对值来找出新的最终值。

.start(time) 方法

        补间动画启动的方法,.start方法接受一个参数 time , 如果加入这个参数,那么补间不会立即开始直到特定时刻才会开始

.stop()方法

        关闭补间动画 .stop() , 关闭这个正在执行的补间动画。

.repeat()方法

        使用该方法可以使动画重复执行,它接受一个参数 , 描述需要重复多少次。

.delay()方法

        延迟执行动画的方法.delay(), 接受一个参数用于控制延迟的具体时间,表示延迟多少时间后才开始执行动画。

.pause()方法

        暂停动画.pause() , 暂停当前补间运动,与resume方法配合使用。

.resume()方法

        恢复动画 .resume() , 恢复这个已经被暂停的补间运动。

.yoyo() 方法

        控制补间重复的模式 .yoyo(), 这个功能只有在使用repeat时才有效果 ,该动画像悠悠球一样来回运动 , 而不是重新开始。

.update()方法

更新补间动画 TWEEN.update() , 动态更新补间运动一般配合 window.requestAnimationFrame 使用

.chain()方法

        链式补间动画,当我们顺序排列不同的补间动画时,比如我们在上一个补间结束的时候立即启动另外一个补间动画,使用 .chain() 方法来做。

//tweenB动画在tweenA动画完成后执行
tweenA.chain(tweenB);

在一些情况下,可能需要将多个补间链接到另一个补间,以使它们(链接的补间)同时开始动画:

tweenA.chain(tweenB,tweenC);

注意:调用 tweenA.chain(tweenB) 实际上修改了tweenA,所以tweenA总是在tweenA完成时启动。 chain的返回值只是tweenA,不是一个新的tween

.getAll()方法

        获取所有的补间组 TWEEN.getAll()

.removeAll()方法

        删除所有的补间组 TWEEN.removeAll()

.add()方法

        新增补间 TWEEN.add(tween) ,添加一个特定的补间 var tween=new TWEEN.Tween()

.remove()方法

        删除补间 TWEEN.remove(tween),删除一个特定的补间var tween=new TWEEN.Tween()

.Group()方法

        新增一个补间组,var Group=TWEEN.Group() , new TWEEN.Tween({ x: 1 }, Group) ,将已经配置好的补间动画进行分组 , TWEEN.update()TWEEN.removeAll() , 不会影响到已经分好组的补间动画。

tween.js回调函数

.onStart()补间动画开始时执行

        补间动画开始时执行,只执行一次,new TWEEN.Tween().onStart((obj)=>{}) , 补间开始时执行,只执行一次, 当使用repeat()重复补间时,不会重复运行 onStart((obj)=>{}) obj补间对象作为第一个参数传入。

.onStop() 停止补间动画时执行

        new TWEEN.Tween().onStop((obj)=>{}) , 当通过 onStop() 显式停止补间时执行,但在正常完成时并且在停止任何可能的链补间之前执行补间,onStop((obj)=>{}) obj补间对象作为第一个参数传入。

.onUpdate() 每次更新时执行

        new TWEEN.Tween().onUpdate((obj)=>{}) , 每次补间更新时执行,返回实际更新后的值, onUpdate((obj)=>{}) obj补间对象作为第一个参数传入。

.onComplete() 补间动画完成时执行

        new TWEEN.Tween().onComplete((obj)=>{}) , 当补间正常完成(即不停止)时执行 , onComplete((obj)=>{}) obj 补间对象作为第一个参数传入。

.onRepeat() 重复补间动画时执行

        new TWEEN.Tween().onRepeat((obj)=>{}) , 当补间动画完成,即将进行重复动画的时候执行 ,onComplete((obj)=>{}) obj 补间对象作为第一个参数传入。

TWEEN.Easing 缓动函数

        tween.js为我们封装好了常用的缓动动画,如线性,二次,三次,四次,五次,正弦,指数,圆形,弹性,下落和弹跳等缓动函数, 以及对应的缓动类型:In (先慢后快)Out (先快后慢)InOut (前半段加速,后半段减速)
Tween.js在Three.js中的应用:为3D动画添加流畅过渡

常见缓动动画

  1. Linear:线性匀速运动效果;
  2. Quadratic:二次方的缓动(t^2)
  3. Cubic:三次方的缓动(t^3)
  4. Quartic:四次方的缓动(t^4)
  5. Quintic:五次方的缓动(t^5)
  6. Sinusoidal:正弦曲线的缓动(sin(t))
  7. Exponential:指数曲线的缓动(2^t)
  8. Circular:圆形曲线的缓动(sqrt(1-t^2))
  9. Elastic:指数衰减的正弦曲线缓动;
  10. Back:超过范围的三次方缓动((s+1)t^3 – st^2)
  11. Bounce:指数衰减的反弹缓动。

以上每个效果都分三个缓动类型,分别是:
easeIn:从0开始加速的缓动,也就是先慢后快;
easeOut:减速到0的缓动,也就是先快后慢;
easeInOut:前半段从0开始加速,后半段减速到0的缓动。

Tween.JS和Three.js示例

Tween.js在Three.js中的应用:为3D动画添加流畅过渡

  1. 导入动画组件库
import * as TWEEN from "three/examples/jsm/libs/tween.module.js"
  1. 创建一个圆柱几何
const sphere1 =  new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 1, 64),new THREE.MeshBasicMaterial( {color: 0xffff00} )
)
sphere1.position.set(0, 10, 0)
sphere1.position.x = 0      
sphere1.position.y = 0      
sphere1.position.z = 0
sphere1.scale.set(-1, -1, 1) 
sphere1.rotation.z = -Math.PI/2 
this.scene.add(sphere1)
  1. 创建tween实例和tween动画
const tween = new TWEEN.Tween(sphere1.position)      
const tweenXZ = new TWEEN.Tween(sphere1.rotation)
const tween2 = new TWEEN.Tween(sphere1.position)
const tween3 = new TWEEN.Tween(sphere1.position)
const tween4 = new TWEEN.Tween(sphere1.position)
//移动
tween.to({x:4},300).onUpdate(()=>{})
//旋转
tweenXZ.to({y:-Math.PI/2},150).onUpdate(()=>{})
//移动
tween2.to({y:-4},300).onUpdate(()=>{})
//移动
tween3.to({x:0},300).onUpdate(()=>{})
//移动
tween4.to({y:0},300).onUpdate(()=>{})
// 一边移动一边旋转,动画在tween动画完成后执行tween2,并带有旋转效果
tween.chain(tween2,tweenXZ)
tween2.chain(tween3,tweenXZ)
tween3.chain(tween4,tweenXZ)      
tween4.chain(tween,tweenXZ)
  1. 设置动画速度运行曲线
tween.easing(TWEEN.Easing.Quadratic.Inout) 
  1. 开启动画
 tween.start()
  1. 开启动画后还不能完全动起来,还需要逐帧更新动画
 animate() {this.controls.update()TWEEN.update()requestAnimationFrame( this.animate );this.renderer.render( this.scene, this.camera );}

完整代码:

<template><div id="container"></div>
</template><script>
import * as THREE from 'three'
// webGL兼容
import WebGL from 'three/examples/jsm/capabilities/WebGL.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
// 轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"
//导入RGBRload加载器
import { RGBELoader } from  "three/examples/jsm/loaders/RGBELoader.js"
//导入场景模型加载器
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
//导入模型解压器
import {DRACOLoader} from "three/examples/jsm/loaders/DRACOLoader.js"
//导入Tween动画组件库
import * as TWEEN from "three/examples/jsm/libs/tween.module.js"
export default {name: 'Three9',components: {},mounted(){this.init()},data(){return {camera: null,  //相机对象scene: null,  //场景对象renderer: null,  //渲染器对象mesh: null,  //网格模型对象Meshmesh2:null,controls:null, //轨道控制器material2:null, //父元素planeMesh:null, //平面rgbeLoacer:null,}},methods:{//随机生成十六进制颜色color16(){//十六进制颜色随机var r = Math.floor(Math.random()*256);var g = Math.floor(Math.random()*256);var b = Math.floor(Math.random()*256);var color = '#'+r.toString(16)+g.toString(16)+b.toString(16);return color;},init(){let container = document.body;//创建一个场景this.scene = new THREE.Scene()//透视摄像机this.camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,700)//创建渲染器this.renderer = new THREE.WebGLRenderer();//渲染器尺寸this.renderer.setSize( window.innerWidth,  window.innerHeight );    // 创建三个球const sphere1 =  new THREE.Mesh(new THREE.CylinderGeometry(1, 1, 1, 64),new THREE.MeshBasicMaterial( {color: 0xffff00} ))sphere1.position.set(0, 10, 0)sphere1.position.x = 0      sphere1.position.y = 0      sphere1.position.z = 0sphere1.scale.set(-1, -1, 1) sphere1.rotation.z = -Math.PI/2 this.scene.add(sphere1)const tween = new TWEEN.Tween(sphere1.position)      const tweenXZ = new TWEEN.Tween(sphere1.rotation)const tween2 = new TWEEN.Tween(sphere1.position)const tween3 = new TWEEN.Tween(sphere1.position)const tween4 = new TWEEN.Tween(sphere1.position)//移动tween.to({x:4},300).onUpdate(()=>{})//旋转tweenXZ.to({y:-Math.PI/2},150).onUpdate(()=>{})//移动tween2.to({y:-4},300).onUpdate(()=>{})//移动tween3.to({x:0},300).onUpdate(()=>{})//移动tween4.to({y:0},300).onUpdate(()=>{})// 一边移动一边旋转,动画在tween动画完成后执行tween2,并带有旋转效果tween.chain(tween2,tweenXZ)tween2.chain(tween3,tweenXZ)tween3.chain(tween4,tweenXZ)      tween4.chain(tween,tweenXZ)//动画运行速度曲线tween.easing(TWEEN.Easing.Quadratic.Inout) tween.start()this.scene.background=new THREE.Color(0x999999)// 设置相机位置this.camera.position.z = 15;   this.camera.position.y =2;  this.camera.position.x = 2; // 看的方向 this.camera.lookAt(0,0,0)//添加世界坐标辅助器const axesHelper = new THREE.AxesHelper(3) this.scene.add( axesHelper );//添加轨道控制器this.controls = new OrbitControls(this.camera,this.renderer.domElement)//添加阻尼带有惯性this.controls.enableDamping = true//设置阻尼系数this.controls.dampingFactor = 0.05//元素中插入canvas对象container.appendChild(this.renderer.domElement); if ( WebGL.isWebGLAvailable() ) {this.animate();} else {const warning = WebGL.getWebGLErrorMessage();document.getElementById( document.body ).appendChild( warning );}},//旋转起来animate() {this.controls.update()TWEEN.update()requestAnimationFrame( this.animate );this.renderer.render( this.scene, this.camera );}}
}
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/846831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 持久化: RDB和AOF

文章目录 ⛄1.RDB持久化&#x1fa82;&#x1fa82;1.1.执行时机&#x1fa82;&#x1fa82;1.2.RDB原理&#x1fa82;&#x1fa82;1.3.小结 ⛄2.AOF持久化&#x1fa82;&#x1fa82;2.1.AOF原理&#x1fa82;&#x1fa82;2.2.AOF配置&#x1fa82;&#x1fa82;2.3.AOF文件…

CRM系统主要是干什么?CRM系统主要功能和作用

什么是CRM 系统&#xff1f;CRM系统到底是干什么的&#xff1f;不同的企业人员该如何利用CRM去解决他们的问题等等&#xff0c;问题太多了&#xff0c;今天来为大家详细介绍。 干货满满&#xff0c;建议收藏&#xff01;&#xff01; 首先第一个问题&#xff0c;什么是CRM系统…

Linux 服务查询命令(包括 服务器、cpu、数据库、中间件)

Linux 服务查询命令&#xff08;包括 服务器、cpu、数据库、中间件&#xff09; Linux获取当前服务器ipLinux使用的是麒麟版本还是cenos版本Linux获取系统信息Linux查询nignx版本 Linux获取当前服务器ip hostname -ILinux使用的是麒麟版本还是cenos版本 这个文件通常包含有关L…

ctfshow jwt web入门

jwt令牌由三部分组成&#xff0c;由.分割 Header Payload Signatureheader示例 {typ: JWT,alg: HS256 }# typ&#xff1a;声明类型 # alg&#xff1a;声明加密的算法 通常直接使用 HMAC SHA256 需要注意的是因为header部分是固定的所以&#xff0c;生成的base64也是固定的以ey…

20、matlab信号波形生成:狄利克雷函数、高斯脉冲和高斯脉冲序列

1、狄利克雷函数生成波形diric()函数 语法&#xff1a;y diric(x,n) 返回n次的狄利克雷函数对输入数组x的元素求值。 1&#xff09;diric()函数 代码 x linspace(-2*pi,2*pi,301);%定义x取值 d6 diric(x,6); d7 diric(x,7); subplot(2,1,1) plot(x,d6) ylabel(n 6) tit…

湖南源点(市场研究)咨询 有效的市场调研是商业定位的基础

本文由湖南&#xff08;市场调研&#xff09;源点咨询编辑发布 近20年&#xff0c;中国购物中心井喷式的发展&#xff0c;经营面积几何倍的增长&#xff0c;但在现今竞争如此激烈的商业环境中&#xff0c;消费者的消费信心不足&#xff0c;购物中心同质化严重&#xff0c;经营…

flyfish3.0.0配置避坑

1.基础环境准备篇 doc/01-基础环境准备篇.md 云智慧/FlyFish - Gitee.com 使用教程里给出的java环境时&#xff0c;可以显示java版本&#xff0c;但是不能显示Maven的版本 改为&#xff1a; export NODE_HOME/usr/local/node/node-v14.19.3-linux-x64 export PATH$NODE_HOME…

100页2秒?我们为什么需要这样的文档解析速度

近期&#xff0c;TextIn通用文档解析完成最新一版产品迭代&#xff0c;将100页文档解析速度提升至最快2秒以内。 P50&#xff08;百页&#xff09; P90&#xff08;百页&#xff09; P95&#xff08;百页&#xff09; P99&#xff08;百页&#xff09; 平均&#xff08;单页…

记某网关系统通用漏洞的挖掘

前言 本篇文章分享一下通用漏洞挖掘的过程&#xff0c;想要获得通用漏洞证书&#xff0c;首先要求是中危及中危以上的通用型漏洞且所属公司的注册资本大于5000万。挖掘一个漏洞其实不难&#xff0c;个人觉得是目标公司资产的搜集。访问CNVD平台发现某网关系统被师傅提交过任意…

V神的傲慢与偏见

原创 | 刘教链 隔夜BTC&#xff08;比特币&#xff09;小幅回升至5日线67.7k附近。前日5.31教链内参“美核心通胀放缓&#xff0c;利好宽松周期落地”[链接]提到&#xff0c;以太坊创始人Vitalik Buterin&#xff08;V神&#xff09;新发表了一篇长文&#xff0c;主题是关于他“…

H6911 DC2.6-40V升压IC 升24V36V48V60V80V100V10A数转模无频闪LED芯片

H6911 DC2.6-40V升压IC是一款升压恒流LED恒流驱动器&#xff0c;具有多种特点&#xff0c;适用于多种的LED照明应用领域。以下是关于该产品的详细解释&#xff1a; 一、产品概述 H6911是一款专为LED照明设计的升压恒流驱动器。它能在2.6至40V的宽电压范围内稳定工作&#xff0c…

性能优化随笔(一)

在软件开发过程中&#xff0c;一般要先实现功能方面的需求&#xff0c;功能方面的需求开发完毕之后&#xff0c;往往会考虑性能方面的优化。在业务发展的初期&#xff0c;性能往往能满足使用的需求&#xff0c;这时性能优化不是必不可少的。随着业务的发展&#xff0c;软件复杂…

Window11开放端口

&#xff08;1&#xff09;打开控制面板&#xff0c;进入【控制面板\系统和安全\Windows Defender 防火墙】 &#xff08;2&#xff09;点击左侧菜单【高级设置】&#xff0c;进入防火墙设置页面 &#xff08;3&#xff09;根据需要选择【入站规则】或者【出站规则】&#xff…

粒子群算法Java实现

粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;是一种受到自然界群体行为启发的优化算法&#xff0c;由James Kennedy和Russell Eberhart于1995年提出。该算法模拟了鸟类或其他动物群体&#xff08;如鱼群&#xff09;的社会和集体行为&#x…

C++:特殊类设计和四种类型转换

一、特殊类设计 1.1 不能被拷贝的类 拷贝只会放生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载&#xff0c;因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98&#xff1a; 1、将拷贝构造函数与赋值运算符重载只…

linux 内核映像差异介绍:vmlinux、zImage、zbImage、image、uImage等

一、背景 Linux内核是整个Linux操作系统的核心部分&#xff0c;它是一个负责与硬件直接交互的软件层&#xff0c;并且提供多种服务和接口&#xff0c;让用户程序能够方便地使用硬件资源。 当我们编译自定义内核时&#xff0c;可以将其生成为以下内核映像之一&#xff1a;vmli…

WordPress博客主题触屏版社区源码

下载地址&#xff1a;WordPress博客主题触屏版社区源码

【Java面试】八、MyBatis篇

文章目录 1、MyBatis执行流程2、MyBatis延迟加载使用3、MyBatis延迟加载的原理4、MyBatis的一级、二级缓存4.1 一级缓存4.2 二级缓存4.3 注意点 5、面试 1、MyBatis执行流程 从mybatis-config.xml读取配置&#xff08;数据库连接信息&#xff0c;xml映射文件&#xff09; 构建…

LeetCode 算法:无重复字符的最长子串c++

原题链接&#x1f517;&#xff1a;无重复字符的最长子串 难度&#xff1a;中等⭐️⭐️ 题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的最长子串的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所…

透视 static 和 extern 对函数的重大影响

目录 一、生命周期和作用域1、生命周期2、作用域 二、static 的影响1、static的作用2、static 修饰局部变量 三、extern 的魔力四、static 与 extern 的协同与冲突1、static修饰全局变量2、static修饰函数 在 C 语言的世界里&#xff0c; static 和 extern 这两个关键字在函数的…