什麼是動作呢?顧名思義它是管理運行環境中所有動作的中樞,通俗點講就是動畫。它也是總個框架核心組件之一,它提供動作的創建、刪除、插入,以及提供對關鍵幀與過渡的諸多操作 ...
動作(Action)系統簡介
什麼是動作呢?顧名思義它是管理運行環境中所有動作的中樞,通俗點講就是動畫。它也是總個框架核心組件之一,它提供動作的創建、刪除、插入,以及提供對關鍵幀與過渡的諸多操作。關鍵幀的過渡可以使用三次貝塞爾曲線,或內置的曲線 linear/ease/ease_in/ease_out/ease_in_out,這也和大多數主流框架以及游戲引擎類似。
動作是什麼原理
動作怎麼驅動視圖進行流暢運動的呢?其實原理很簡單,我們可以把動作系統看做一個獨立的系統與視圖或渲染完全不相關。它們之間的關係是動作自身的變化最終會映射調視圖,這個過程是通過調用視圖暴露的公有方法或屬性來完成的。這個過程完全是單向的,且視圖不會向動作發出任何指令。
比如說現在創建了一個新的關鍵幀動作,給它設置兩個關鍵幀,且x的值經過1秒鐘從0變化到100。這個過程是動作自身發生的變化並且帶動與之相關的視圖一同發生改變,請記住這個過程視圖是被動的,而動作才是主動的發生改變。
import { ngui, Div } from 'ngui';
import KeyframeAction from 'ngui/action';
var div = new Div();
var act = new KeyframeAction();
act.add({ x: 0, time: 0 });
act.add({ x: 100, time: 1e3/*毫秒*/ });
div.width = 50;
div.height = 50;
div.backgroundColor = '#f00';
div.action = act;
div.appendTo(ngui.root);
act.play();
動作類別
以下是框架提供的幾個類型與繼承聯繫
註:帶*號的為抽象類型或協議沒有構造函數
Action*
這是所有動作的基礎類型,也是抽象類型不可以直接被實例。
提供了一些基本的api操作,播放
,停止
,跳轉
等,具體可查看API手冊。
GroupAction*
這是個集合的動作類型,提供子動作的添加刪除插入。有了子動作就可以幫你實現更加複雜的動畫場景。
它也有兩個具體的子類型 SpawnAction 、SequenceAction。
SpawnAction
並行動作顧名思義即就是它的子動作都是並行運行的。並且以最長子動作的時長做為自身的時長來執行動作,較短時長的子動作則在結尾等待動作的結束或一個迴圈的的終止。
SequenceAction
串列動作這個比較好理解,子動作一個接著一個執行,全部執行完成後結束或開始新的迴圈。
KeyframeAction與Frame
關鍵幀動作這是動作系統的核心。所有動作的實現均在這裡完成它是動作系統基本單元,前面的GroupAction只有包含KeyframeAction類型的動作才有真正的義意。
而關鍵幀動作又包含理更加基本的元素關鍵幀
Frame,關鍵幀包含的屬性與CSS
屬性是同名的且與所有視圖的屬性都是對應關鍵。通俗的說比如View上會有x
屬性而Frame上也會有x
屬性,如果關鍵幀上有視圖上並不存在的屬性,那麼這個屬性對視圖是無效的。比如View上就不存在width
屬性那麼這個屬性的改變不會影響到View,但如果綁定的視圖是Div那麼width
的改變一定會影響到它,這與CSS
樣式表類似。
看下麵的例子:
// 這是有效的動作
var act1 = new KeyframeAction();
var div = new Div();
div.backgroundColor = '#f00';
act1.add({ width: 10, height: 10 });
act1.add({ width: 100, height: 100, time: 1e3 });
div.action = act1;
act1.paly();
// 這是無效的
var act2 = new KeyframeAction();
var view = new View();
act2.add({ width: 10, height: 10 });
act2.add({ width: 100, height: 100, time: 1e3 });
view.action = act2;
act2.paly();
View.action屬性
View.action做為View的一個屬性可接收多種類型的參數,之前給大家展示的例子中創建動作是很繁瑣的,但active
提供多種類型的參數類型的支持,包括json
數據與Action
對像實例本身。前面的例子中已介紹過Action
方式,下麵著重說json
數據方法。大家也可研讀ngui.js
與action.js
中的源代碼,其它View.action屬性只是做簡單的調用轉發,功能的實現其實是在action.js
文件中的create()
方法里實現的。
看例子:
// 這是創建KeyframeAction
var div = new Div();
div.action = {
keyframe: [
{ x: 0 },
{ x: 100, time: 500 },
{ x: 0, time: 1000 },
],
loop: -1,
};
var div2 = new Div();
div.action = [
{ x: 0 },
{ x: 100, time: 500 },
];
// 這是創建SequenceAction
var div3 = new Div();
div3.action = {
seq: [
[ // 這是個子KeyframeAction
{ x: 0 },
{ x: 100, time: 1e3 },
],
{ // 這是個子SpawnAction
spawn: [
[ // 這是個子KeyframeAction
{ y : 100 }, { y: 200, time: 2e3 }
],
[ // 這是個子KeyframeAction
{ width : 200 }, { width: 100, time: 1e3 }
],
]
}
],
};
// 這是創建SpawnAction
var div4 = new Div();
div4.action = {
spawn: [ // 這裡只包含一個子KeyframeAction
{x: 0}, {x: 200, time: 2e3}
]
};
大家可以看到上面的例子中有4種典型的創建方法。主要看你給的json
數據是否存在這三個屬性seq
、spawn
、keyframe
,對應SpawnAction、SequenceAction、KeyframeAction,外加一個json
數據類型檢查,數據類型為數組就創建KeyframeAction。並且這可以嵌套使用。
View.transition()方法
這是一個簡單創建簡單過渡動畫的方法,實現原型為action.js
的transition()
方法,與View.action一樣View.transition()只做簡單的轉發。
典型應用:
view.transition({
time: 1000,
y: 100,
x: 100,
})
具體可查閱手冊。
View.onActionKeyframe與View.onActionLoop
這兩個事件是由動作產生併發送的。
-
View.onActionKeyframe
為動作執行到達關鍵幀時觸發。因為畫面渲染是固定的幀率,觸發總是發生在幀的渲染時,所以可能會與理想中的時間值有所誤差提前或延後,這個延時值會保存在事件數據的delay
上。提前為負數,延時為正數。 -
View.onActionLoop
動作迴圈開始時觸發,第一次執行動作並不會觸發。同樣它也會有延時,也同樣記錄在delay
。