首頁 >web前端 >js教程 >tween.js 中文使用指南

tween.js 中文使用指南

小云云
小云云原創
2018-01-08 09:24:335622瀏覽

本文主要介紹了詳解tween.js 中文使用指南,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧,希望能幫助大家。

補間(動畫)是一個概念,允許你以平滑的方式更改物件的屬性。你只需告訴它哪些屬性要更改,當補間結束運行時它們應該具有哪些最終值,以及這需要多長時間,補間引擎將負責計算從起始點到結束點的值。

例如,position物件擁有x和y兩個座標:


var position = { x: 100, y: 0 }

如果你想將x座標的值從100變成200,你應該這麼做:


// 首先为位置创建一个补间(tween)
var tween = new TWEEN.Tween(position);

// 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置
tween.to({ x: 200 }, 1000);

一般來說這樣還不夠,tween 已經被創建了,但是它還沒有被激活(使用),你需要這樣啟動:


// 启动
tween.start();

最後,想要成功的完成這個效果,你需要在主函數中呼叫TWEEN.update,如下使用:


animate();

function animate() {
 requestAnimationFrame(animate);
 // [...]
 TWEEN.update();
 // [...]
}

這樣在更新每幀的時候都會運行補間動畫;經過1秒後(1000 毫秒) position.x將會變成200。

除非你在控制台中印出 x 的值,不然你看不到它的變化。你可能想要使用onUpdate 回呼:


tween.onUpdate(function(object) {
 console.log(object.x);
});

tips:你可能在這裡取得不到object.x ,具體的見我提的這個issue

#這個函數將會在動畫每次更新的時候被呼叫;這種情況發生的頻率取決於很多因素- 例如,電腦或設備的速度有多快(以及如何繁忙)。

到目前為止,我們只使用補間動畫向控制台輸出值,但是您可以將它與three.js 物件結合:


var tween = new TWEEN.Tween(cube.position)
 .to({ x: 100, y: 100, z: 100 }, 10000)
 .start();

animate();

function animate() {
 requestAnimationFrame(animate);
 TWEEN.update();
 threeRenderer.render(scene, camera);
}

在這種情況下,因為three.js渲染器將在渲染之前查看物件的位置,所以不需要使用明確的onUpdate回呼。

你可能也注意到了一些不同的地方:tween.js 可以鍊式呼叫! 每個tween函數都會回傳tween實例,所以你可以重寫下面的程式碼:


var tween = new TWEEN.Tween(position);
tween.to({ x: 200 }, 1000);
tween.start();

改成這樣:


var tween = new TWEEN.Tween(position)
 .to({ x: 200 }, 1000)
 .start();

在將會看到很多例子,所以熟悉它是很好的!例如04-simplest 這個例子。

tween.js的動畫

Tween.js 不會自行運作。你需要明確的呼叫 update 方法來告訴它何時運行。建議的方法是在主動畫循環中執行這個操作。使用 requestAnimationFrame 呼叫此循環以獲得最佳的圖形效能。

例如之前這個範例:


animate();

function animate() {
 requestAnimationFrame(animate);
 // [...]
 TWEEN.update();
 // [...]
}

如果呼叫的時候不傳入參數,update 將會判斷目前時間點以決定自上次執行以來已經有多久。

當然你也可以傳遞一個明確的時間參數給 update


TWEEN.update(100);

意思是"更新時間 = 100 毫秒"。你可以使用它來確保程式碼中的所有時間相關函數都使用相同的時間值。例如,假設你有一個播放器,並且希望同步運行補間。 你的 animate 函數可能看起來像這樣:


var currentTime = player.currentTime;
TWEEN.update(currentTime);

我們使用明確的時間值進行單元測試。你可以看下tests.js 這個例子,看看我們如何用不同的值呼叫TWEEN.update() 來模擬時間傳遞。

控制一個補間

start 和stop

到目前為止,我們已經了解了Tween.start方法,但還有更多的方法來控制單一補間。 也許最重要的一個是 star 對應的方法:停止 。 如果你想要取消一個補間,只要呼叫這個方法通過一個單獨的補間:


tween.stop();

停止一個從未開始或已經停止的補間沒有任何效果。 沒有錯誤被拋出。

start 方法接受一個參數 time。如果你使用它,那麼補間不會立即開始,直到特定時刻,否則會盡快啟動(i.e 即在下次呼叫 TWEEN.update)。

update

補間也有一個更新的方法---這實際上是由 TWEEN.update 呼叫的。 你通常不需要直接呼叫它,除非你是個 瘋狂的hacker。

chain

當你順序排列不同的補間時,事情會變得有趣,例如在上一個補間結束的時候立即啟動另外一個補間。我們稱這為鍊式補間,這使用 chain 方法去做。因此,為了使tweenB 在tewwnA 啟動:


tweenA.chain(tweenB);

或者,對於一個無限的鍊式,設定tweenA一旦tweenB完成就開始:


#
tweenA.chain(tweenB);
tweenB.chain(tweenA);

關於無限的鍊式檢視Hello world 。

在其他情況下,您可能需要將多個補間連結到另一個補間,以使它們(連結的補間)同時開始動畫:


tweenA.chain(tweenB,tweenC);

警告:呼叫tweenA.chain(tweenB) 實際上修改了tweenA,所以tweenA總是在tweenA完成時啟動。 chain 的回傳值只是tweenA,不是新的tween。

repeat

#

如果你想让一个补间永远重复,你可以链接到自己,但更好的方法是使用 repeat 方法。 它接受一个参数,描述第一个补间完成后需要多少次重复


tween.repeat(10); // 循环10次
tween.repeat(Infinity); // 无限循环

补间的总次数将是重复参数加上一个初始补间。查看 Repeat。

yoyo

这个功能只有在独自使用 repeat 时才有效果。 活跃时,补间的行为将像 yoyo 一样,i.e 它会从起始值和结束值之间跳出,而不是从头开始重复相同的顺序。

delay

更复杂的安排可能需要在实际开始运行之前延迟补间。 你可以使用 delay 方法来做到这一点


tween.delay(1000);
tween.start();

将在调用启动方法后的1秒钟后开始执行。

控制所有补间

在 TWEEN 全局对象中可以找到以下方法,除了 update 之外,通常不需要使用其中的大部分对象。

TWEEN.update(time)

我们已经讨论过这种方法。 它用于更新所有活动的补间。

如果 time 不指定,它将使用当前时间。

TWEEN.getAll and TWEEN.removeAll

用于获取对活动 tweens 数组的引用,并分别仅从一个调用中将它们全部从数组中删除

TWEEN.add(tween) and TWEEN.remove(tween)

用于将补间添加到活动补间的列表,或者分别从列表中删除特定的补间。

这些方法通常只在内部使用,但是如果您想要做一些有趣的事情,则会被暴露。

控制补间组

使用 TWEEN 单例来管理补间可能会导致包含许多组件的大型应用程序出现问题。 在这些情况下,您可能希望创建自己的更小的补间组。

示例:交叉组件冲突

如果使用 TWEEN 有多个组件,并且每个组件都想管理自己的一组补间,则可能发生冲突。 如果一个组件调用 TWEEN.update() 或 TWEEN.removeAll(),则其他组件的补间也将被更新或删除。

创建你自己的补间组

为了解决这个问题,每个组件都可以创建自己的 TWEEN.Group 实例(这是全局的 TWEEN 对象在内部使用的)。 实例化新的补间时,可以将这些组作为第二个可选参数传入:


var groupA = new TWEEN.Group();
var groupB = new TWEEN.Group();

var tweenA = new TWEEN.Tween({ x: 1 }, groupA)
 .to({ x: 10 }, 100)
 .start();

var tweenB = new TWEEN.Tween({ x: 1 }, groupB)
 .to({ x: 10 }, 100)
 .start();

var tweenC = new TWEEN.Tween({ x: 1 })
 .to({ x: 10 }, 100)
 .start();

groupA.update(); // 只更新tweenA
groupB.update(); // 只更新tweenB
TWEEN.update(); // 只更新tweenC

groupA.removeAll(); // 只移除tweenA
groupB.removeAll(); // 只移除tweenB
TWEEN.removeAll(); // 只移除tweenC

通过这种方式,每个组件都可以处理创建,更新和销毁自己的一组补间。

改变缓动功能

Tween.js 将以线性方式执行值之间的插值(即缓动),所以变化将与流逝的时间成正比。 这是可以预见的,但在视觉上也是相当无趣的。 不要担心 - 使用缓动方法可以轻松更改此行为。 例如:


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

这将导致缓慢地开始向最终值变化,向中间加速,然后迅速达到其最终值,相反,TWEEN.Easing.Quadratic.Out 一开始会加速,但随着值的接近最终放缓。

可用的缓动函数:TWEEN.Easing

tween.js提供了一些现有的缓动功能。它们按照它们表示的方程式进行分组:线性,二次,三次,四次,五次,正弦,指数,圆形,弹性,背部和弹跳,然后是缓动型:In,Out和InOut。

除非您已经熟悉这些概念,否则这些名称可能不会对您说什么,所以您可能需要查看 Graphs 示例,该示例将一个页面中的所有曲线进行图形化,以便比较它们如何看待一瞥。

这些功能是从 Robert Penner 慷慨地提供几年前作为自由软件提供的原始方程派生而来的,但是已经被优化以便与JavaScript很好地发挥作用。

使用自定义缓动功能

您不仅可以使用任何现有的功能,还可以提供您自己的功能,只要遵循一些约定即可:

它必须接受一个参数:

k: 缓动过程,或我们的补间所处的时间有多长。允许的值在[0,1]的范围内。

它必须根据输入参数返回一个值。

不管要修改多少个属性,easing函数在每次更新时只调用一次。 然后将结果与初始值以及这个值和最终值之间的差值(delta)一起使用,就像这个伪代码一样:


easedElapsed = easing(k);
for each property:
 newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed;

对于更注重性能表现的人来说:只有在补间上调用 start() 时才会计算增量值。

因此,让我们假设您想使用一个缓解值的自定义缓动函数,但是将 Math.floor 应用于输出,所以只返回整数部分,从而产生一种梯级输出:


function tenStepEasing(k) {
 return Math.floor(k * 10) / 10;
}

你可以通过简单地调用它的缓动方法来使用它,就像我们之前看到的那样:


tween.easing(tenStepEasing);

查看 graphs for custom easing functions 示例,以查看这个动作(还有一些用于生成步进函数的元编程)。

回调函数

另一个强大的特性是能够在每个补间的生命周期的特定时间运行自己的功能。 当更改属性不够时,通常需要这样做。

例如,假设你正在试图给一些不能直接访问属性的对象设置动画,但是需要你调用setter。 您可以使用 update 回调来读取新的更新值,然后手动调用setters。 所有的回调函数都将补间对象作为唯一的参数。


var trickyObjTween = new TWEEN.Tween({
 propertyA: trickyObj.getPropertyA(),
 propertyB: trickyObj.getPropertyB()
})
 .to({ propertyA: 100, propertyB: 200 })
 .onUpdate(function(object) {
 object.setA( object.propertyA );
 object.setB( object.propertyB );
 });

或者想象一下,当一个补间开始时,你想播放声音。你可以使用 start 回调:


var tween = new TWEEN.Tween(obj)
 .to({ x: 100 })
 .onStart(function() {
 sound.play();
 });

每个回调的范围是补间对象--在这种情况下,是 obj。

onStart

在补间开始之前执行--i.e. 在计算之前。每个补间只能执行一次,i.e. 当通过 repeat() 重复补间时,它将不会运行。

同步到其他事件或触发您要在补间启动时发生的操作是非常好的。

补间对象作为第一个参数传入。

onStop

当通过 stop() 显式停止补间时执行,但在正常完成时并且在停止任何可能的链补间之前执行补间。

补间对象作为第一个参数传入。

onUpdate

每次补间更新时执行,实际更新后的值。

补间对象作为第一个参数传入。

onComplete

当补间正常完成(即不停止)时执行。

补间对象作为第一个参数传入。

高级补间

相对值

使用 to 方法时,也可以使用相对值。 当tween启动时,Tween.js将读取当前属性值并应用相对值来找出新的最终值。

但是你需要使用引号,否则这些值将被视为绝对的。 我们来看一个例子:


// This will make the `x` property be 100, always
var absoluteTween = new TWEEN.Tween(absoluteObj).to({ x: 100 });

// Suppose absoluteObj.x is 0 now
absoluteTween.start(); // Makes x go to 100

// Suppose absoluteObj.x is -100 now
absoluteTween.start(); // Makes x go to 100

// In contrast...

// This will make the `x` property be 100 units more,
// relative to the actual value when it starts
var relativeTween = new TWEEN.Tween(relativeObj).to({ x: "+100" });

// Suppose relativeObj.x is 0 now
relativeTween.start(); // Makes x go to 0 +100 = 100

// Suppose relativeObj.x is -100 now
relativeTween.start(); // Makes x go to -100 +100 = 0

查看09_relative_values 示例。

补间值的数组

除了补间为绝对值或相对值之外,还可以让Tween.js跨一系列值更改属性。 要做到这一点,你只需要指定一个数组的值,而不是一个属性的单个值。 例如:


var tween = new TWEEN.Tween(relativeObj).to({ x: [0, -100, 100] });

将使 x 从初始值变为0,-100和100。

这些值的计算方法如下:

  1. 首先,补间进度如常计算

  2. 进度(从0到1)用作插值函数的输入

  3. 基于进度和值的数组,生成内插值

例如,当补间刚刚启动(进度为0)时,插值函数将返回数组中的第一个值。 当补间到一半时,插值函数将返回一个大约在数组中间的值,当补间结束时,插值函数将返回最后一个值。

您可以使用插值方法更改插值函数。 例如:


tween.interpolation( TWEEN.Interpolation.Bezier );

以下值可用:

  1. TWEEN.Interpolation.Linear

  2. TWEEN.Interpolation.Bezier

  3. TWEEN.Interpolation.CatmullRom

默认是 Linear。

请注意,插值函数对于与同一补间中的数组进行补间的所有属性是全局的。
您不能使用数组和线性函数进行属性A的更改,也不能使用相同的补间进行数组B的属性B和Bezier函数的更改; 您应该使用运行在同一对象上的两个补间对象,但修改不同的属性并使用不同的插值函数。

查看 06_array_interpolation 示例。

获得最佳性能

虽然Tween.js试图自己执行,但是没有什么能够阻止你以一种反作用的方式使用它。 这里有一些方法可以避免在使用Tween.js时(或者在网页中进行动画制作时)减慢项目速度。

使用高性能的CSS

当您尝试在页面中设置元素的位置时,最简单的解决方案是为 top 和 left 属性设置动画,如下所示:


var element = document.getElementById('myElement');
var tween = new TWEEN.Tween({ top: 0, left: 0 })
 .to({ top: 100, left: 100 }, 1000)
 .onUpdate(function(object) {
 element.style.top = object.top + 'px';
 element.style.left = object.left + 'px';
 });

但这实际上是效率低下的,因为改变这些属性会迫使浏览器在每次更新时重新计算布局,这是非常昂贵的操作。 相反的,您应该使用 transform,这不会使布局无效,并且在可能的情况下也将被硬件加速,比如:


var element = document.getElementById('myElement');
var tween = new TWEEN.Tween({ top: 0, left: 0 })
 .to({ top: 100, left: 100 }, 1000)
 .onUpdate(function(object) {
 element.style.transform = 'translate(' + object.left + 'px, ' + object.top + 'px);';
 });

但是,如果您的动画需求非常简单,那么在适用的情况下使用CSS动画或转换可能会更好,以便浏览器尽可能优化。
当您的动画需要涉及复杂的布局时,Tween.js是非常有用的,也就是说,您需要将多个补间同步到一起,在完成一些动作之后,循环多次等等。

对垃圾收集器(别名GC)

如果你使用onUpdate回呼函數,你需要非常小心的使用它。 因為這個函數每秒鐘會被調用很多次,所以如果每次更新都要花費很多的代價,那麼你可能會阻塞主線程並導致可怕的結果,或者如果你的操作涉及到內存分配的話, 垃圾收集器運作太頻繁,也導致結果。 所以只是不要做些事情中的其中一個。 保持你的onUpdate回呼非常輕量級,並確保在開發時也使用記憶體分析器。

瘋狂的補間

這是你可能不常使用的東西,但你可以在Tween.js之外使用補間公式。 畢竟,它們只是功能。 所以你可以使用它們來計算平滑曲線作為輸入資料。

例如,他們用來在 這個實驗 中產生音訊資料。

相關推薦:

tween.js的使用實例詳解

簡單的動畫庫封裝tween.js實例教學

Tween.js動畫詳細介紹

以上是tween.js 中文使用指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn