tween.js 中文使用指南

来源:https://www.cnblogs.com/wwhhq/archive/2018/01/07/8228059.html
-Advertisement-
Play Games

tween.js 英文使用指南 首先來看個例子: hello,tween.js 補間(動畫)(來自 in between)是一個概念,允許你以平滑的方式更改對象的屬性。你只需告訴它哪些屬性要更改,當補間結束運行時它們應該具有哪些最終值,以及這需要多長時間,補間引擎將負責計算從起始點到結束點的值。 例 ...


tween.js 英文使用指南首先來看個例子: hello,tween.js

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

例如,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。

這些值的計算方法如下:


  • 首先,補間進度如常計算

  • 進度(從0到1)用作插值函數的輸入

  • 基於進度和值的數組,生成內插值


例如,當補間剛剛啟動(進度為0)時,插值函數將返回數組中的第一個值。 當補間到一半時,插值函數將返回一個大約在數組中間的值,當補間結束時,插值函數將返回最後一個值。

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

tween.interpolation( TWEEN.Interpolation.Bezier );

以下值可用:

  • TWEEN.Interpolation.Linear
  • TWEEN.Interpolation.Bezier
  • 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之外使用補間公式。 畢竟,它們只是功能。 所以你可以使用它們來計算平滑曲線作為輸入數據。
例如,他們用於在 這個實驗 中生成音頻數據。

https://github.com/zhaoqize/blog/issues/10

前端庫


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Javascipt數組 在Javascript中數組的做用是:使用單獨的變數名來儲存一系列的值。 數組只有一個屬性,就是length,length表示的數組所占記憶體空間的數目。 1.創建數組 創建數組方法1: 創建數組方法2: 2.數組合併 數組合併方法1: 數組合併方法2: 3.把數組合成字元串 ...
  • Javascript流程式控制制 1.條件語句 (1)if(exp)執行一句代碼 (2)if(exp){執行代碼段;} (3)if(exp){exp為true執行代碼段}else{exp為false執行的代碼段} (4)if...else if... (5)if嵌套 2.迴圈語句 (1)for 迴圈 ( ...
  • Koa 是由 Express 原班人馬打造的超輕量服務端框架 與 Express 相比,除了自由度更高,可以自行引入中間件之外,更重要的是使用了 ES6 + async,從而避免了回調地獄 不過也是因為代碼升級,所以 Koa2 需要 v7.60 以上的 node.js 環境 一、創建項目 手動創建一 ...
  • Javascript變數 javascript變數是什麼呢?javascript變數就是用來儲存數據的一個容器。 1.javascript變數應該註意什麼? (1)變數必須以字母開頭 (2)變數也能以 $ 和 _ 符號開頭,但是我們不推薦這麼做 (3)變數名稱對大小寫敏感。Y 和 y 是不同的變數 ...
  • 說起css佈局,那麼一定得聊聊盒模型,清除浮動,position,display什麼的,但本篇本不是講這些基礎知識的,而是給出各種佈局的解決方案。 水平居中佈局 首先我們來看看水平居中 1.margin + 定寬 相必是個前端都見過,這定寬的水平居中,我們還可以用下麵這種來實現不定寬的 2. tab ...
  • 1. Object類型 創建對象的方式 1) 構造函數方式 var obj = new Object(); // Object為構造函數 2)字面量方式 var obj = {} 2. Array類型 ECMAscript數組的每一項可以保存任何類型的數據 創建數組的方式 1)var color = ...
  • React Learn Note 3 React學習筆記(三) 標簽(空格分隔): React JavaScript 二、元素渲染 元素是構成react應用的最小單位。 元素是普通的對象。 元素是構成組件的一個部分。 1. 將元素渲染到DOM中 ``中的所有內容都將由React DOM來管理。稱為“ ...
  • 恢復內容開始 js介紹 最近學習了js,那麼我今天給大家介紹下js。希望對初學者有些幫助。 js就是常說的JavaScript。JavaScript是目前世界上最流行的編程語言之一。這門語言可用於HTML和WEB,更可以廣泛的用於伺服器、PC、筆記本電腦、平板電腦和智能手機等設備。JavaScrip ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...