本文實例講述了用隊列模擬jquery的動畫演算法。分享給大家供大家參考。具體分析如下:
Aaron最近瘋狂的愛上了演算法研究,估計又要死傷不少腦細胞了,我喜歡撿現成的,可以省些力氣。發現他寫的一段源碼,運行一下,還蠻好玩的,於是拿來分析一下,一來吸收下里邊的營養,二來加深一下源碼學習的功力。話說這源碼還真是提高js內功的一大秘決,不信,就跟我一起來品味一下吧。
*/
(function($) {
window.$ = $;
})(function() {
//用來符合ID字串
//(?:表示這裡不分組) ,參考正規的內容
//不過我個人認為把*改成 號會比較好,因為#後至少要一個字元吧
var rquickExpr = /^(?:#([w-]*))$/;
//一看便是jquery的重度病患
function aQuery(selector) {
return new aQuery.fn.init(selector);
}
/**
* 動畫
* @return {[type]} [description]
*/
var animation = function() {
var self = {};
var Queue = []; //動畫佇列
var fireing = false //動畫鎖
var first = true; //透過add介面觸發
var getStyle = function(obj, attr) {
return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, false)[attr];
}
//這裡邊都是特定的動畫效果,沒有什麼難懂的
var makeAnim = function(element, options, func) {
var width = options.width
//包裝了特定的執行演算法
//css3
//setTimeout
element.style.webkitTransitionDuration = '2000ms';
element.style.webkitTransform = 'translate3d(' width 'px,0,0)';
//監聽動畫結束
element.addEventListener('webkitTransitionEnd', function() {
func()
});
}
var _fire = function() {
//加入動畫觸發
if (!fireing) {
var onceRun = Queue.shift();
if (onceRun) {
//防止重複觸發性
fireing = true;
//next
onceRun(function() {
fireing = false;
//這裡且巧妙的產生了連續召喚的效果
_fire();
});
} else {
fireing = true;
}
}
}
return self = {
//增加佇列
add: function(element, options) {
//這裡是整個演算法的關鍵
//相當於以陣列中新增一個函數
//[function(func){},...]
//也就是_fire中的onceRun方法,而func也就是在那時傳進去的。
//在Aaron的程式設計中很喜歡使用此技巧,例如預先編譯之類的。
Queue.push(function(func) {
makeAnim(element, options, func);
});
//若有一個佇列立刻觸發動畫
if (first && Queue.length) {
//這個開關很好的起到了控制後面新增的元素進行排隊的作用
且為 false;
//這裡以直接運作_fire();
//Aaron喜歡在A,且故意加上一個self.fire出來,或許他是深謀遠慮
self.fire();
}
},
//觸發
fire: function() {
_fire();
}
}
}();
aQuery.fn = aQuery.prototype = {
run: function(options) {
animation.add(this.element, options);
return this;
}
}
var init = aQuery.fn.init = function(selector) {
var match = rquickExpr.exec(selector);
var element = document.getElementById(match[1])
this.element = element;
return this;
}
//差點小看了這一行程式碼
//jquery的樣子學的不錯
//直接aQuery.fn.init = aQuery.fn不是更好?
//多一個init變數無非是想減少查詢罷了,優化的想法無所不在。
init.prototype = aQuery.fn;
return aQuery;
}());
//dom
var oDiv = document.getElementById('div1');
//呼叫
oDiv.onclick = function() {
$('#div1').run({
'width': '500'
}).run({
'width': '300'
}).run({
'width': '1000'
});
};
附上html就可以自己調式了。要記得用chrome瀏覽哦。
希望本文所述對大家的jQuery程式設計有所幫助。