摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調(diào)用中,進行同步調(diào)用動畫是異步的就是連續(xù)調(diào)用二作用通過樣式將元素從一個狀態(tài)改變?yōu)榱硪粋€狀態(tài)源碼之前有說過是的方法源碼行是否是空對象,方法執(zhí)行單個動畫的封裝的本質(zhì)是執(zhí)行
前言:
需要先看 jQuery源碼解析之$.queue()、$.dequeue()和jQuery.Callbacks()
一、舉例
divA 的寬度先變成 500px,再變成 300px,最后變成 1000px:
這是A
二、$().animate()
作用:
通過 CSS 樣式將元素從一個狀態(tài)改變?yōu)榱硪粋€狀態(tài)
源碼:
//之前有說過: jQuery.fn.extend() 是$()的方法
jQuery.fn.extend( {
//源碼8062行
//{"width": "500"}
animate: function( prop, speed, easing, callback ) {
//是否是空對象,false
var empty = jQuery.isEmptyObject( prop ),
// optall={
// complete:function(){jQuery.dequeue()},
// old:false,
// duration: 400,
// easing: undefined,
// queue:"fx",
// }
//undefined undefined undefined
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won"t be lost
//Animation 方法執(zhí)行單個動畫的封裝
//doAnimation的本質(zhì)是執(zhí)行Animation方法
//this:目標元素
//{"width": "500"}
//optall={xxx}
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations, or finishing resolves immediately
//finish是數(shù)據(jù)緩存的一個全局變量
//如果為true,立即終止動畫
if ( empty || dataPriv.get( this, "finish" ) ) {
anim.stop( true );
}
};
//注意這個
//自身的.finish=自身
doAnimation.finish = doAnimation;
return empty || optall.queue === false ?
this.each( doAnimation ) :
//一般走這里
//通過 queue 調(diào)度動畫之間的銜接
//optall.queue:"fx"
//doAnimation:function(){}
this.queue( optall.queue, doAnimation );
},
})
解析:
(1)jQuery.speed()
作用:
初始化動畫對象的屬性
源碼:
//源碼8009行
//undefiend undefined undefined
//作用是返回一個經(jīng)過修改的opt對象
jQuery.speed = function( speed, easing, fn ) {
// opt={
// complete:false,
// duration: undefined,
// easing: undefined,
// }
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
complete: fn || !fn && easing ||
isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !isFunction( easing ) && easing
};
// Go to the end state if fx are off
/*這邊是為opt.duration賦值的*/
//undefiend
if ( jQuery.fx.off ) {
opt.duration = 0;
} else {
if ( typeof opt.duration !== "number" ) {
if ( opt.duration in jQuery.fx.speeds ) {
opt.duration = jQuery.fx.speeds[ opt.duration ];
} else {
//走這邊
//_default=400
opt.duration = jQuery.fx.speeds._default;
}
}
}
/*為opt.queue賦值*/
// Normalize opt.queue - true/undefined/null -> "fx"
//注意這個==,是模糊判斷
if ( opt.queue == null || opt.queue === true ) {
opt.queue = "fx";
}
// Queueing
/*為opt.old賦值*/
opt.old = opt.complete;
opt.complete = function() {
if ( isFunction( opt.old ) ) {
opt.old.call( this );
}
//如果queue有值得話,就出隊列
//因為queue默認為"fx",所以一般會觸發(fā)dequeue操作
if ( opt.queue ) {
//this指目標元素
//opt.queue
jQuery.dequeue( this, opt.queue );
}
};
//此時的opt為:
// opt={
// complete:function(){jQuery.dequeue()},
// old:false,
// duration: 400,
// easing: undefined,
// queue:"fx",
// }
return opt;
};
解析:
通過傳入的三個參數(shù),對opt對象進行處理,如果三個參數(shù)都為undefined的話,opt等于:
opt={
complete:function(){jQuery.dequeue()},
old:false,
duration: 400,
easing: undefined,
queue:"fx",
}
(2)animate內(nèi)部做了什么?
作用:
animate內(nèi)部封裝了一個doAnimation觸發(fā)器,觸發(fā)器觸發(fā)就會運行Animation方法,animate最后返回的是queue()方法,注意queue()方法的參數(shù)帶有觸發(fā)器doAnimation
(3)$().queue()
作用:
執(zhí)行入隊操作(jQuery.queue()),如果是fx動畫的話,同時執(zhí)行出隊操作(jQuery.dequeue())
源碼
這個方法上篇文章已經(jīng)分析過了,這里就簡單分析下:
jQuery.fn.extend( {
//optall.queue:"fx"
//doAnimation:function(){}
//fx動畫的話,就執(zhí)行dequeue(),也就是隊首callback函數(shù)
queue: function( type, data ) {
//返回的是數(shù)組[doAnimate,doAnimate,xxx]
var queue = jQuery.queue( this, type, data );
//初始化hooks
jQuery._queueHooks( this, type );
/*專門為fx動畫做處理*/
//如果隊首沒有鎖的話,直接運行隊首元素
if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
},
解析:
inprogress是動畫隊列的鎖,目的是保證上個動畫執(zhí)行結(jié)束后,再去執(zhí)行下個動畫
每入隊一個doAnimate函數(shù),如果隊首沒有inprogress 鎖的話,就會出隊去運行一個doAnimate函數(shù)
jQuery._queueHooks()的意義在于添加一個empty.remove()方法,用來清空隊列queue
(4)jQuery.queue()
作用:
上篇文章也分析過了,就是將doAnimate函數(shù)push進queue數(shù)組中
(5)jQuery.dequeue()
作用:
如果隊首元素不是inprogress,而是doAnimation方法,則先將doAnimation出隊,再讓inprogress入隊首,再運行doAnimation方法;
如果隊首元素是inprogress的話,則移除鎖
如果隊列為空的話,則清空queue,節(jié)省內(nèi)存
源碼:
//源碼4624行
//目標元素,"type"
dequeue: function( elem, type ) {
//"type"
type = type || "fx";
//get,獲取目標元素的隊列
var queue = jQuery.queue( elem, type ),
//長度
startLength = queue.length,
//去除對首元素,并返回該元素
fn = queue.shift(),
//確保該隊列有一個hooks
hooks = jQuery._queueHooks( elem, type ),
//next相當于dequeue的觸發(fā)器
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
//如果fn="inprogress",說明是fx動畫隊列正在出隊,就移除inprogress
if ( fn === "inprogress" ) {
fn = queue.shift();
startLength--;
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
//如果是fx動畫隊列的話,就添加inprogress標志,來防止自動出隊執(zhí)行
//意思應該是等上一個動畫執(zhí)行完畢后,再執(zhí)行下一個動畫
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
// Clear up the last queue stop function
//刪除hooks的stop屬性方法
delete hooks.stop;
//遞歸dequeue方法
fn.call( elem, next, hooks );
}
console.log(startLength,"startLength4669")
//如果隊列是一個空數(shù)組,并且hooks存在的話,清除該隊列
if ( !startLength && hooks ) {
//進行隊列清理
hooks.empty.fire();
console.log(hooks.empty.fire(),"bbbb4671")
}
},
解析:
循環(huán)同步運行多個doAnimation()方法,直到隊列為空
綜上,除doAnimation內(nèi)的邏輯外,整個$().animate()的流程圖為:
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/105057.html
摘要:根據(jù)的間隔,利用循環(huán)執(zhí)行,從而達到渲染動畫的目的。最后,附上的流程圖,建議配合整個的流程圖二的最后一個圖一起看下篇將會模擬實現(xiàn)方法,敬請期待完 三、doAnimation內(nèi)部的Animation()方法作用:$().animate()核心方法 源碼: //animate()核心方法 //源碼7844行 //elem:目標元素 //this:目標元素 //{widt...
摘要:事件在完成過渡后觸發(fā),這里當做單個動畫完成的信號,觸發(fā)后,會告知下個動畫進行下圖的實現(xiàn)將在下篇文章貼出完 showImg(https://segmentfault.com/img/remote/1460000019618970); showImg(https://segmentfault.com/img/remote/1460000019618971); 根據(jù)上圖實現(xiàn)除doAnimat...
閱讀 686·2019-08-30 15:55
閱讀 1081·2019-08-29 15:35
閱讀 1426·2019-08-29 13:48
閱讀 2203·2019-08-26 13:29
閱讀 3098·2019-08-23 18:26
閱讀 1453·2019-08-23 18:20
閱讀 2973·2019-08-23 16:43
閱讀 2868·2019-08-23 15:58