12 使用 Tween.js 建立補間動畫
Tween是什麼
補間(動畫)(來自 in-between)是一個概念,允許你以平滑的方式更改物件的屬性。你只需告訴它哪些屬性要更改,當補間結束執行時它們應該具有哪些最終值,以及這需要多長時間,補間引擎將負責計算從起始點到結束點的值。
在Three.js
中,我們也有一些修改模型的位置,旋轉和縮放的需求,我們無法直接在webgl
中使用css3
動畫,所以,Tween
給我們提供了一個很好的解決方案。
接下來,我們首先檢視一下如何實現Tween
的簡單應用。
簡單應用
閒話少說,我們先實現一個Three.js
應用Tween
的案例:
- 首先,建立一個
position
物件,裡面儲存當前立方體的位置資料:
var position = {x:-40, y:0, z:-30};
- 然後,通過當前的物件建立一個補間
Tween
:
tween = new TWEEN.Tween(position);
- 設定每一個屬性的目標位置,並告訴
Tween
在2000毫秒內移動到目標位置:
tween.to({x:40, y:30, z:30}, 2000);
- 我們設定
Tween
物件的每次更新的回撥,在每次資料更新以後,將立方體的位置更新掉:
tween.onUpdate(function (pos) {
cube.position.set(pos.x, pos.y, pos.z);
});
Tween
物件不會直接執行,需要我們去呼叫start()
方法啟用:
tween.start();
- 想要完成整個過程,我們還需要在每幀裡面呼叫
TWEEN.update
,來觸發Tween
物件更新位置:
function render() {
//更新Tween
TWEEN.update();
control.update();
renderer.render(scene, camera);
}
鏈式呼叫
Tween
外掛也支援鏈式呼叫的方法,並且還會修改例項化時傳入的物件,所以我們可以將:
//設定tween var position = {x:-40, y:0, z:-30}; tween = new TWEEN.Tween(position); //設定移動的目標和移動時間 tween.to({x:40, y:30, z:30}, 2000); //設定每次更新的回撥,然後修改幾何體的位置 tween.onUpdate(function (pos) { cube.position.set(pos.x, pos.y, pos.z); });
簡化為鏈式:
//直接鏈式實現tween
tween = new TWEEN.Tween(cube.position).to({x:40, y:30, z:30}, 2000);
Tween物件方法
.start()
這個方法是我們最早了解的Tween
的方法,如果你想啟用一個補間,請使用這個方法
tween.start();
start
方法還接受一個引數。如果你使用他,那麼補間不會立即開始,會從第一次呼叫TWEEN.update
後開始計時,如果設定的時間已經小於計時的總時間,那計算出來的位置資料將是引數設定時間開始後,執行到的所在位置。
.stop()
這個方法剛好和start
方法對應,如果你想取消一個補間,直接呼叫這個方法即可:
tween.stop();
.update()
每一個補間其實都有一個更新的方法,只不過我們通過使用TWEEN.update
去呼叫。我們一般不會單獨去呼叫。
.chain()
當你順序排列不同的補間時,事情會變得有趣,例如在上一個補間結束的時候立即啟動另外一個補間。我們稱這為鏈式補間,這使用 chain
方法去做。因此,為了使 tweenB
在 tewwnA
啟動:
tweenA.chain(tweenB);
或者,對於一個無限的鏈式,設定tweenA一旦tweenB完成就開始:
tweenA.chain(tweenB);
tweenB.chain(tweenA);
在其他情況下,您可能需要將多個補間連結到另一個補間,以使它們(連結的補間)同時開始動畫:
tweenA.chain(tweenB,tweenC);
警告:呼叫 tweenA.chain(tweenB) 實際上修改了tweenA,所以tweenA總是在tweenA完成時啟動。 chain 的返回值只是tweenA,不是一個新的tween。 接下來我們檢視一下鏈式補間的案例: 案例檢視地址:點選這裡 案例程式碼檢視地址:點選這裡
.repeat()
如果你想讓一個補間永遠重複,你可以連結到自己,但更好的方法是使用 repeat
方法。 它接受一個引數,描述第一個補間完成後需要多少次重複:
tween.repeat(10); // 迴圈10次
tween.repeat(Infinity); // 無限迴圈
我們可以將simple.html
裡面的呼叫改成無限迴圈:
tween = new TWEEN.Tween(cube.position).to({x:40, y:30, z:30}, 2000).repeat(Infinity);
.yoyo()
這個功能只有在補間使用repeat
方法時才有效果。我們設定yoyo
以後,位置的切換效果就會變為從頭到尾,從尾到頭這樣的迴圈。
單個補間的無限從頭到尾迴圈可以寫成這樣:
tween = new TWEEN.Tween(cube.position).to({x:40, y:30, z:30}, 2000).repeat(Infinity).yoyo(true);
.delay()
這個方法用於控制啟用前的延時,即觸發start
事件後,需要延時到設定的delay
時間,才會真正啟用:
tween.delay(1000);
tween.start();
回撥函式
在之前的simple.html
中,我們是在每次更新回撥中獲取更新後的位置資訊:
//設定每次更新的回撥,然後修改幾何體的位置
tween.onUpdate(function (pos) {
cube.position.set(pos.x, pos.y, pos.z);
});
下面列一下補間支援的所有的回撥函式:
onStart
在補間計算開始前的回撥,每個補間只能觸發一下,即使使用repeat
方法迴圈,這個回撥也只被觸發一次。
onStop
通過呼叫補間的stop
方法停止的補間會觸發當前回撥,如果是正常完成的補間將不會觸發此回撥。
onUpdate
每次補間更新後,我們可以在此回撥中獲取更新後的值。
onComplete
當補間正常完成時,將會觸發此回撥。通過使用stop
停止的補間將不會觸發此回撥。