摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調用中,進行同步調用動畫是異步的就是連續調用二作用通過樣式將元素從一個狀態改變為另一個狀態源碼之前有說過是的方法源碼行是否是空對象,方法執行單個動畫的封裝的本質是執行
前言:
需要先看 jQuery源碼解析之$.queue()、$.dequeue()和jQuery.Callbacks()
一、舉例
divA 的寬度先變成 500px,再變成 300px,最后變成 1000px:
這是A
二、$().animate()
作用:
通過 CSS 樣式將元素從一個狀態改變為另一個狀態
源碼:
//之前有說過: 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 方法執行單個動畫的封裝 //doAnimation的本質是執行Animation方法 //this:目標元素 //{"width": "500"} //optall={xxx} var anim = Animation( this, jQuery.extend( {}, prop ), optall ); // Empty animations, or finishing resolves immediately //finish是數據緩存的一個全局變量 //如果為true,立即終止動畫 if ( empty || dataPriv.get( this, "finish" ) ) { anim.stop( true ); } }; //注意這個 //自身的.finish=自身 doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : //一般走這里 //通過 queue 調度動畫之間的銜接 //optall.queue:"fx" //doAnimation:function(){} this.queue( optall.queue, doAnimation ); }, })
解析:
(1)jQuery.speed()
作用:
初始化動畫對象的屬性
源碼:
//源碼8009行 //undefiend undefined undefined //作用是返回一個經過修改的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",所以一般會觸發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; };
解析:
通過傳入的三個參數,對opt對象進行處理,如果三個參數都為undefined的話,opt等于:
opt={ complete:function(){jQuery.dequeue()}, old:false, duration: 400, easing: undefined, queue:"fx", }
(2)animate內部做了什么?
作用:
animate內部封裝了一個doAnimation觸發器,觸發器觸發就會運行Animation方法,animate最后返回的是queue()方法,注意queue()方法的參數帶有觸發器doAnimation
(3)$().queue()
作用:
執行入隊操作(jQuery.queue()),如果是fx動畫的話,同時執行出隊操作(jQuery.dequeue())
源碼
這個方法上篇文章已經分析過了,這里就簡單分析下:
jQuery.fn.extend( { //optall.queue:"fx" //doAnimation:function(){} //fx動畫的話,就執行dequeue(),也就是隊首callback函數 queue: function( type, data ) { //返回的是數組[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是動畫隊列的鎖,目的是保證上個動畫執行結束后,再去執行下個動畫
每入隊一個doAnimate函數,如果隊首沒有inprogress 鎖的話,就會出隊去運行一個doAnimate函數
jQuery._queueHooks()的意義在于添加一個empty.remove()方法,用來清空隊列queue
(4)jQuery.queue()
作用:
上篇文章也分析過了,就是將doAnimate函數push進queue數組中
(5)jQuery.dequeue()
作用:
如果隊首元素不是inprogress,而是doAnimation方法,則先將doAnimation出隊,再讓inprogress入隊首,再運行doAnimation方法;
如果隊首元素是inprogress的話,則移除鎖
如果隊列為空的話,則清空queue,節省內存
源碼:
//源碼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的觸發器 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標志,來防止自動出隊執行 //意思應該是等上一個動畫執行完畢后,再執行下一個動畫 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") //如果隊列是一個空數組,并且hooks存在的話,清除該隊列 if ( !startLength && hooks ) { //進行隊列清理 hooks.empty.fire(); console.log(hooks.empty.fire(),"bbbb4671") } },
解析:
循環同步運行多個doAnimation()方法,直到隊列為空
綜上,除doAnimation內的邏輯外,整個$().animate()的流程圖為:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105057.html
摘要:根據的間隔,利用循環執行,從而達到渲染動畫的目的。最后,附上的流程圖,建議配合整個的流程圖二的最后一個圖一起看下篇將會模擬實現方法,敬請期待完 三、doAnimation內部的Animation()方法作用:$().animate()核心方法 源碼: //animate()核心方法 //源碼7844行 //elem:目標元素 //this:目標元素 //{widt...
摘要:事件在完成過渡后觸發,這里當做單個動畫完成的信號,觸發后,會告知下個動畫進行下圖的實現將在下篇文章貼出完 showImg(https://segmentfault.com/img/remote/1460000019618970); showImg(https://segmentfault.com/img/remote/1460000019618971); 根據上圖實現除doAnimat...
閱讀 535·2019-08-30 15:55
閱讀 944·2019-08-29 15:35
閱讀 1198·2019-08-29 13:48
閱讀 1910·2019-08-26 13:29
閱讀 2933·2019-08-23 18:26
閱讀 1237·2019-08-23 18:20
閱讀 2834·2019-08-23 16:43
閱讀 2709·2019-08-23 15:58