對于 jQuery 的動畫的設計我們要分 2 個層面理解:
- 每一個動畫效果可以看作一個獨立的動畫對象,每個對象都實現了針對自己這個動畫的生命周期的控制
- 動畫對象與動畫對象之間其實是沒有直接關系,但是為了做到連續(xù)調用就需要引入一套隊列機制也就是 Queue 來控制對象之間的轉換的控制
動畫的源碼:
animate: function(prop, speed, easing, callback) {
doAnimation = function() {
var anim = Animation(this, args, optall);
};
this.queue(optall.queue, doAnimation);
}
這個代碼縮減了,但是我們上面提到的最重要的 2 點這里都涉及到了:通過 queue 調度動畫的之間的銜接,Animation 方法執(zhí)行單個動畫的封裝。
jQuery 在 queue 的調度上涉及了一個關鍵的處理:同步與異步代碼同時執(zhí)行,同步收集動畫序列,異步調用序列,看看整個調用的流程是這樣的:
- 通過多個 animate 方法形成動畫鏈,那么這個動畫鏈其實都是會加入到 queue 隊列里面
- 在每一次 queue 方法中會把動畫數據寫到隊列中,然后取出隊列中的第一個序列通過 dequeue 方法執(zhí)行
- 開始執(zhí)行之前寫一個進程鎖“inprogress”到 queue 里面,代表這個動畫還在執(zhí)行中,防止同個序列的多個動畫重復執(zhí)行,這個就是異步執(zhí)行同步收集的處理方案
- 此時動畫開始了,這里注意動畫是在異步執(zhí)行的同步的代碼,繼續(xù)調用下一個 animate
- 執(zhí)行同樣的 animate 方法邏輯但是此時問題來了,動畫可能還在執(zhí)行可是后續(xù)的 animate 還在繼續(xù)調用,所以這個時候后面的動畫代碼就需要等待了(進程鎖)
- 隊列頭是有一把“inprogress”進程鎖的,那么這時候動畫只需要加入隊列,但是可以通過 inprogress 是否存在來判斷是否執(zhí)行
- 所有的 animate 方法在加入隊列都是按照以上的邏輯依次執(zhí)行,動畫執(zhí)行完畢了就會有一個結束通知,然后從 queue 取出第一個隊列繼續(xù)執(zhí)行了,如此循環(huán)
以上是整個動畫的調度一個流程,其實都是利用隊列異步的空閑然后執(zhí)行同步的代碼,這樣在處理上是沒有浪費資源的,而且精確度也是最高的。