首页 > 其他分享 >Threejs -- TweenJS自定义flyTo函数

Threejs -- TweenJS自定义flyTo函数

时间:2023-09-27 18:33:36浏览次数:51  
标签:TWEEN Threejs 自定义 -- 动画片 tween 缓动 easing options

TweenJS

参考文档

笔记末尾附自定义flyTo函数

动画库tweenjs简介和引入项目

TweenJS是一个有javascript语言编写的补间动画库,如果需要tweenjs辅助你生成动画,对于任何前端web项目,你都可以选择tweenjs库。

如果你是用three.js开发web3d项目,使用tween.js辅助three.js生成动画效果也是比较好的选择,比如微信小游戏跳一跳中的模型伸缩、跳动动作。

.html引入

写一个简单小例子或者学习的时候,你可以在.html文件中直接引入tween.js
github下载的文件中tween.umd.js添到.html文件中,TWEEN会作为全局变量存在,你通过TWEEN可以访问tweenjs所有方法。

<script src="./tween.js-master/dist/tween.umd.js"></script>

npm安装

在工程化开发的时候,可以通过npm命令进行安装tween.js模块

npm i @tweenjs/tween.js@^18
const TWEEN = require('@tweenjs/tween.js')
// 或者
import TWEEN from '@tweenjs/tween.js'
a.chain(b)
b.chain(a)
// 这样写可以进行连续循环动画

回调函数

tweenjs库提供了onStartonUpdateonComplete等用于控制动画执行的回调函数。

// x:模型x坐标
var pos = {x: 0}
var tween = new TWEEN.Tween(pos).to({x: 100}, 4000)
// 开始执行:动画片段tween开始执行的时候触发onStart
.onStart(function() {
  mesh.material.color.set(0xff0000)
})
// 正在执行:动画片段tween正在执行的时候触发onUpdate
// tween动画执行期间,.onUpdate()重复执行
.onUpdate(function() {
  // 更新mesh坐标x
  mesh.position.x = pos.x
})
// 执行完成:动画片段tween执行完成的时候触发onComplete
.onComplete(function() {
  mesh.material.color.set(0x00ff00)
})

onStop

手动执行tween.stop()停止动画会触发回调函数onStop执行。

一段tween完成后多个tween同步执行

通过构造函数TWEEN.Tween()可以实例化一个对象tween,该对象tween表示一段动画。

动画片段A执行完成后,动画片段B和C基本同步执行。

a.chain(b) // 动画片段a完成接着执行动画片段b
b.chain(c)

d.chain(e)
e.chain(f)

// 动画片段a执行完触发回调函数a.onComplete执行
a.onComplete(function() {
  d.start() // 动画片段d开始执行
})

或者

// a.chain(b) // 动画片段a完成接着执行动画片段b
b.chain(c)

d.chain(e)
e.chain(f)

// 动画片段a执行完触发回调函数a.onComplete执行
a.onComplete(function() {
  b.start() // 触发动画片段b、d开始执行
  d.start() 
})

批量创建tween动画片段并串连

// 生成mesh沿着系列轨迹坐标pointArr运动的动画
var pointArr = [
  0,0,-150,
  100,0,-150,
  100,0,-50,
  0,0,-50,
  0,0,50,
  100,0,50,
  100,0,150,
  0,0,150
] 
var pos = { x: pointArr[0], y: pointArr[1], z: pointArr[2] } // mesh坐标
var tweenArr = [] // 所有动画片段tween的集合
// 批量创建动画片段tween
for (var i = 3;i < pointArr.length; i+=3) { // 跳过pointArr第一个点坐标
  var tween = new TWEEN.Tween(pos)
  .to({ x: pointArr[i], y: pointArr[i+1], z: pointArr[i+2] }, 1000)
  .onUpdate(function() {
    mesh.position.x = pos.x
    mesh.position.z = pos.z
  })
  tweenArr.push(tween)
}
// 批量连接所有动画片段
for (var i = 0;i < tweenArr.length - 1; i++) {
  tweenArr[i].chain(tweenArr[i + 1])
}
tweenArr[0].start() // 播放一串动画片段

.easing()方法(缓动算法)

动画片段tween通过.easing()方法可以设置缓动算法。在一些动画场景中你设置合理的缓动算法,可以让动画看起来非常自然,比如一辆车从静止进入匀速状态,动画最好有一个加速过程的过渡,对于这个加速的方式就可以通过缓动算法实现。

形象理解,所谓缓动,你可以理解为运动缓缓加速的过程,缓动算法就是运动加速的算法,推广一下,减速理,再推广一下,不一定针对运动,比如颜色渐变也可以类比运动加减速。

.easing()语法格式

// easing函数:缓动算法(运动效果)
// easing类型:定义缓动算法起作用地方
tween.easing(TWEEN.Easing.easing函数.easing类型)

easing类型(定义缓动算法起作用地方)

easing函数和easing类型都有多种方式,可以自由组合使用(Linear除外)。

// 动画开始缓动方式(类比加速启动)
tween.easing(TWEEN.Easing.Sinusoidal.In)
// 动画结束缓动方式(类比减速刹车)
tween.easing(TWEEN.Easing.Sinusoidal.Out)
// 同时设置In和Out
tween.easing(TWEEN.Easing.Sinusoidal.InOut)

easing函数(定义缓动算法)

Linear:默认效果可以不设置,可以理解为没有加速过程直接进入匀速状态,或者说没有减速过程,直接刹车。
Quadratic:二次方的缓动(t^2
Cubic:三次方的缓动(t^3
Quartic:四次方的缓动(t^4
Quintic:五次方的缓动(t^5
Sinusoidal:正弦曲线的缓动(sin(t)
Exponential:指数曲线的缓动(2^t)启动非常慢,后面快
Circular:圆形曲线的缓动(sqrt(1-t^2)会有弹性衰减往复运动感
Elastic:指数衰减的正弦曲线缓动;TWEEN.Easing.Elastic.inout会有弹性衰减往复运动感
Back:超过范围的三次方缓动((s+1)*t^3 - s*t^2)会有弹性衰减往复运动感
Bounce:指数衰减的反弹缓动,会有弹性衰减往复运动感

匀速运动(特殊情况说明)

Linear:默认效果可以不设置,可以理解为没有加速过程直接进入匀速状态,或者说没有减速过程,直接刹车。

注意:匀速设置TWEEN.Easing.Linear.None(默认效果可以不设置)

对于Linear不要设置TWEEN.Easing.Linear.InTWEEN.Easing.Linear.OutTWEEN.Easing.Linear.InOut,会报错

官方案例03_graphs.html

官方案例03_graphs.html,可以查看各种缓动算法的曲线效果图。

模型颜色渐变动画

var obj = {r: 1, g: 0, b: 0}
var tween = new TWEEN.Tween(obj) // 创建一段tween动画
tween.to({r: 0, g: 1, b: 1}, 4000)
tween.onUpdate(function() {
  mesh.material.color.setRGB(obj.r, obj.g, obj.b)
})
tween.start()
function render() {TWEEN.update() ...}

自定义 flyTo 函数

/**
 * 
 * @param {Object} options TWEEN参数
 * @param {Boolean} e 是否清除所有的TWEEN动画
 * @param {Function} callback 回调函数
 */
function flyTo(options, e, callback) {
	const cameraPos = camera.position.clone(); 
	const controlsTar = controls.target.clone();
	options.position = options.position || [cameraPos.x, cameraPos.y, cameraPos.z];
	options.controls = options.controls || [controlsTar.x, controlsTar.y, controlsTar.z];
	options.duration = options.duration || 1000;
	options.easing = options.easing || TWEEN.Easing.Linear.None;
	e !== false && TWEEN.removeAll();
	const r = new TWEEN.Tween({
		number: 0,
		x1: cameraPos.x,
		y1: cameraPos.y,
		z1: cameraPos.z,
		x2: controlsTar.x,
		y2: controlsTar.y,
		z2: controlsTar.z
	}).to({
		number: 1,
		x1: options.position[0],
		y1: options.position[1],
		z1: options.position[2],
		x2: options.controls[0],
		y2: options.controls[1],
		z2: options.controls[2]
	}, options.duration).easing(options.easing)
	.onStart(() => {
		controls.enabled = false
	}).onUpdate(e => {
		controls.enabled = false
		let cpx = (options.position[0] - cameraPos.x) * e.number + cameraPos.x
			, cpy = (options.position[1] - cameraPos.y) * e.number + cameraPos.y
			, cpz = (options.position[2] - cameraPos.z) * e.number + cameraPos.z
			, ctx = (options.controls[0] - controlsTar.x) * e.number + controlsTar.x
			, cty = (options.controls[1] - controlsTar.y) * e.number + controlsTar.y
			, ctz = (options.controls[2] - controlsTar.z) * e.number + controlsTar.z;

		camera.position.set(cpx, cpy, cpz);
		controls.target.set(ctx, cty, ctz);
		controls.update()
	}).onComplete(() => {
		controls.enabled = true
		if (callback && typeof callback === 'function' ) {
			callback()
		}
	}).start()
}

标签:TWEEN,Threejs,自定义,--,动画片,tween,缓动,easing,options
From: https://www.cnblogs.com/lisaShare/p/17733403.html

相关文章

  • MySQL运维2-主从复制
    一、主从复制概念主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从服务器中,然后在从服务器上对这些日志重新执行也叫重做,从而使得从数据库和主库的数据保持同步。MySQL支持一台主库同时向多台从库进行赋值,从库同时也可以作为其他从服务器的主库,实现链式复制。......
  • 8个维度全面解读:CI/CD和DevOps到底有什么不同
    CI/CD是一种让程序员能迅速并可靠地更新代码的做法。而DevOps则包括一系列方法和思想,这些让开发和运维的人都能更好地协作,使得整个产品从设计到使用都能更加高效地完成。尽管CI/CD和DevOps都是为了让软件开发更高效,但它们在具体怎么做上有很多不同点。CI/CD与DevOpsCI/CD是一组......
  • SQL Server 重复记录,查询,筛查,指定保留
    Select*From表xWhere重复字段In(Select重复字段From表GroupBy重复字段HavingCount(*)>1)OrderBY重复字段DELETExFROM表xWhere重复字段In(Select重复字段From表GroupBy重复字段HavingCount(*)>1)ANDIdNOTIN(SelectMax(ID......
  • centos7.9 扩容swap分区
    情况说明:在VMwarevsphere的虚拟化平台下,为了快速部署虚拟服务器,我们常常使用模板部署虚拟机。但真实业务有时要求的文件系统分区和大小常常与模板不同,这时便需要自定义硬件资源和使用LVM方式扩容。在定义硬盘的时候我们可以在原有的硬盘上直接增加,然后虚拟机创建完成后再进入系......
  • 案例实操基础版--加载数据+数据清洗(5W条数据)
    我看到了这个跟着实操一下!1、加载数据(已经提供了csv文件)建库建表--->这个比较简单,根据文件的字段名创建合适的表;createtablemsg(msg_timestringcomment"消息发送时间",sender_namestringcomment"发送人昵称",sender_accountstringcomment"发送人帐......
  • 记录--Vue3 + Fabricjs 定制国庆专属头像
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助生在国旗下,长在春风里!国庆将至,采黎为大家带来定制头像2.0(国庆头像),让我们用代码的形式为祖国庆生!欢迎大家点赞收藏加关注哦前言想看效果或者想定制春节头像的小伙伴请直奔效果区域;想一睹定制头像2.0小工具的......
  • CS61A: Structure and Interpretation of Computer Programs 笔记
    FunctionsEnvironmentDiagrams:左侧为Frames,右侧为Objects。Name类似变量名,它们存储在Frame中,指向各种各样的Objects,比如值或函数。一个Name同时只能指向一个Object,但可以改变自身指向,不受“类型”影响(Name根本没有固定的“类型”概念)。Assignment的过程是计算'='......
  • golang-waitgroup
    说明golang通过waitgroup来实现并发控制,用法跟java的CountDownLatch 效果一样 WaitGroup的使用场景和方法我们通过goroutine运行一个或者一组任务,需要关心这组任务执行完了进行通知WaitGroup如同它的字面意思,就是等待一组goroutine运行完成,主要有三个方法组成:Add(de......
  • 2023/09/27
    四则运算课堂测试三 1、可定制(数量):输入大的出题数量值,测试一下系统是否崩溃,反向查找系统是否优化的余地;2、定制操作数的个数、定制是否有乘除法、定制是否有括号(随机加入)、定制数值范围(确定操作数的取值范围);3、定义方法实现错题集、错题重练并记录错题的次数功能。4、能处理......
  • 敏捷开发的实施要素和实现敏捷的实际改进
    ​敏捷开发的实施要素如下:个体和交互:胜过过程和工具。可以工作的软件:胜过面面俱到的文档。客户合作:胜过合同谈判。响应变化:胜过遵循计划。敏捷开发过程是一个增量的、迭代的过程,责任人、开发人员和用户要能够共同维持其步调稳定延续。实现敏捷的实际改进可以从以下方面入......