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