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,一经查实,立即删除!

相关文章

【基于Raft的k-v存储数据库实现】

基于Raft的k-v存储数据库实现 基本概念1. 什么是分布式系统2. 什么是Raft协议3. 什么是序列化和反序列化4. RPC相关5. c11的部分新特性6. 什么是共识&#xff0c;一致性算法7. 共识算法要满足的性质8. Raft中的一些重要概念8.1 Raft是如何保证一个Term只有一个Leader的&#xf…

《软件需求分析与系统设计》课程设计报告——英语考试与评分系统

《软件需求分析与系统设计》课程设计报告 课题名称: 英语考试与评分系统 姓名: xxx 专业: 软件工程 班级: xxx 院系: 信息与工程学院 指导教师: xxx 时间: 2023年11月21日 一、题目概述 1. 系统简介 英语考试与评分系统是一套高效的管理软件,旨在应对大学英语…

PTA R6-1 寻找链表元素的前驱结点

本题要求实现一个函数&#xff0c;可查找单链表(无监督元)中某个元素的前驱结点。例如链表中的元素为1&#xff0c;6&#xff0c;3&#xff0c;2&#xff0c;4&#xff0c;查找3的前驱为6。如果表中无此元素或没有前驱则返回空指针。 函数接口定义&#xff1a; ptr pre (ptr …

监控易监测对象及指标之:全面监控阿里专有云Redis

随着企业业务的快速发展&#xff0c;数据库作为支撑业务运行的核心组件&#xff0c;其性能和稳定性显得尤为重要。Redis&#xff0c;作为一款高性能的内存数据库&#xff0c;广泛应用于缓存、消息队列、分布式锁等场景。在阿里专有云环境中&#xff0c;Redis的性能监控更是至关…

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文件…

Python项目开发实战:AI智能图像识别工具(案例教程)

一、项目背景与意义 随着人工智能技术的快速发展,图像识别技术已成为众多领域的关键技术之一。从安防监控到自动驾驶,从医疗诊断到智能家居,图像识别技术都发挥着举足轻重的作用。因此,开发一款高效、准确的AI智能图像识别工具具有重要的现实意义和应用价值。 二、项目目标…

【MyBatisPlus】MyBatisPlus介绍与使用

【MyBatisPlus】MyBatisPlus介绍与使用 文章目录 【MyBatisPlus】MyBatisPlus介绍与使用1、什么MyBatisPlus2、MyBatisPlus的CRUD操作3、MyBatisPlus分页使用 1、什么MyBatisPlus MyBatisPlus&#xff08;简称MP&#xff09;是基于MyBatis框架基础上开发的增强型工具&#xff0…

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

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

uniapp 小程序运行报错plus...

plus.XXX方法是针对Android安卓的 解决方式&#xff1a; 在有关代码内添加 #ifdef APP-PLUS // #ifdef APP-PLUS ... 代码块 ....// #endif

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

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

达梦数据库备份还原bak

s1.–关闭数据库 2.–数据库还原&#xff1a; 到数据库bin下 执行 /dmrman RESTORE DATABASE /dm/data/xx/dm.ini FROM BACKUPSET /dm/data/backup/DB_xxx_FULL_2024_06_02_23_00_04;3.–数据库恢复&#xff1a; ./dmrman RECOVER DATABASE /dm/data/tjwater/dm.ini FROM BACKU…

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…

C++中的‘friend‘关键字

目录 友元函数&#xff08;Friend Function&#xff09; 友元类&#xff08;Friend Class&#xff09; 友元函数模板&#xff08;Friend Function Template&#xff09; 友元类模板&#xff08;Friend Class Template&#xff09; 总结 摘要 在 C 中&#xff0c;friend 关…

英伟达算力芯片为什么能够“一统天下”

英伟达算力芯片能够一统天下&#xff0c;主要归因于以下几个关键因素&#xff1a; 技术创新与产品优势&#xff1a; 英伟达自1993年成立以来&#xff0c;一直在GPU和AI芯片领域进行持续的技术创新。特别是随着深度神经网络技术的突破&#xff0c;英伟达借助CUDA平台在人工智能…

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

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

C语言题目:求具有abcd=(ab+cd)^2性质的四位数

题目描述 3025这个数具有一种独特的性质&#xff1a;将它平分为二段&#xff0c;即30和25&#xff0c;使之相加后求平方&#xff0c;即(3025)2&#xff0c;恰好等于3025本身。请求出具有这样性质的全部四位数 输入格式 无 输出格式 满足题意的数全部四位数(从小到大输出,且…

mybatis执行自定义sql

背景 在开发过程中遇到一个需求&#xff1a;希望从数据库中读取预先定义好的sql&#xff0c;根据传参进行参数预处理后执行sql语句。结合项目实际情况我决定使用mybatis执行预定义sql。 实现过程 缓存我们自定义的sql语句 MappedStatement ms new MappedStatement.Builder(co…

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…

【面试题-006】java中的垃圾回算法有哪些?

Java中的垃圾回收&#xff08;Garbage Collection&#xff0c;简称GC&#xff09;是指自动内存管理的一种机制&#xff0c;用于回收不再使用的对象占用的内存。Java中的垃圾回收算法主要有以下几种&#xff1a; 标记-清除&#xff08;Mark-Sweep&#xff09;算法&#xff1a; …