jQuery 1.9.1源碼分析系列(十五)動畫處理之緩動動畫核心Tween
在jQuery內(nèi)部函數(shù)Animation中調(diào)用到了createTweens()來創(chuàng)建緩動動畫組,創(chuàng)建完成后的結(jié)果為:
可以看到上面的緩動動畫組有四個原子動畫組成。每一個原子動畫的信息都包含在里面了。
仔細查看createTweens函數(shù),實際上就是遍歷調(diào)用了tweeners ["*"]的數(shù)組中的函數(shù)(實際上就只有一個元素)。
function createTweens( animation, props ) { jQuery.each( props, function( prop, value ) { var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), index = 0, length = collection.length; for ( ; index < length; index++ ) { if ( collection[ index ].call( animation, prop, value ) ) { // we're done with this property return; } } }); }
再次查看這個tweeners ["*"][0]函數(shù),主要代碼如下
function( prop, value ) { var end, unit, //根據(jù)css特征值獲取緩動動畫結(jié)構(gòu) tween = this.createTween( prop, value ), parts = rfxnum.exec( value ), target = tween.cur(), start = +target || 0, scale = 1, maxIterations = 20; if ( parts ) { end = +parts[2]; unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); //非像素單位的屬性 if ( unit !== "px" && start ) { // 從一個非零起點開始迭代, //對于當前屬性,如果它使用相同的單位這一過程將是微不足道 // 后備為end,或一個簡單的常量 start = jQuery.css( tween.elem, prop, true ) || end || 1; do { //如果前一次迭代為零,加倍,直到我們得到*東西* //使用字符串倍增因子,所以我們不會偶然看到scale不改變 scale = scale || ".5"; // 調(diào)整和運行 start = start / scale; jQuery.style( tween.elem, prop, start + unit ); // 更新scale, 默認0或NaN從tween.cur()獲取 // 跳出循環(huán),如果scale不變或完成時, 或者我們已經(jīng)覺得已經(jīng)足夠了 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); } tween.unit = unit; tween.start = start; //如果提供了+=/-=記號,表示我們正在做一個相對的動畫 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; } return tween; }] };
可以看出除了hide/show兩種動畫外的其他動畫都經(jīng)過tweeners ["*"][0]這個函數(shù)封裝了動畫組。其中有幾個關(guān)鍵的數(shù)組start/end/unit。特別是對非像素單位的動畫start值獲取費了一番功夫。
還有一個比較關(guān)鍵的地方是都用了this.createTween獲取單個css特征的基礎(chǔ)的動畫特征。而animation. createTween中直接調(diào)用jQuery.Tween來處理。接下來我們詳解之。
a.jQuery.Tween
--------------------------------------------------------------------------------
jQuery.Tween的結(jié)構(gòu)和jQuery類似
function Tween( elem, options, prop, end, easing ) { return new Tween.prototype.init( elem, options, prop, end, easing ); } jQuery.Tween = Tween; Tween.prototype = { constructor: Tween, init: function( elem, options, prop, end, easing, unit ) { this.elem = elem; this.prop = prop; this.easing = easing || "swing"; this.options = options; this.start = this.now = this.cur(); this.end = end; this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); }, cur: function() {...}, run: function( percent ) {...} }; Tween.prototype.init.prototype = Tween.prototype;
是不是有一種很熟悉的趕腳。
里面cur函數(shù)用來獲取當前的css特征值
cur: function() { var hooks = Tween.propHooks[ this.prop ]; return hooks && hooks.get ? hooks.get( this ) : Tween.propHooks._default.get( this ); },
而run函數(shù)則會在每個動畫時間點上對正在進行的動畫的每個特征值進行處理。
主要是兩個步驟:
1.計算動畫當前進度pos和動畫當前位置now
//如果有動畫時長則使用jQuery.easing計算出緩動動畫進度eased,否則進度eased為percent //并根據(jù)進度得到當前動畫位置now if ( this.options.duration ) { this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration ); } else { this.pos = eased = percent; } this.now = ( this.end - this.start ) * eased + this.start;
2.根據(jù)當前進度情況設(shè)置css特征值
//設(shè)置css特征值 if ( hooks && hooks.set ) { hooks.set( this ); } else { Tween.propHooks._default.set( this ); } return this;
可見生成緩動動畫這一步處理才是整個動畫的核心:
創(chuàng)建緩動動畫組,每一個原子動畫都包含了每一個原子css屬性動畫的各種必要參數(shù)以及動畫函數(shù)
不同的是hide/show直接在defaultPrefilter中創(chuàng)建了這個緩動動畫組(所有的屬性都默認是px單位),其他的動畫在調(diào)用createTweens時創(chuàng)建緩動動畫組。
還記不記得在創(chuàng)建動畫的時候有個tick函數(shù),這個tick函數(shù)會在每隔一個步長的時間調(diào)用一次
tick = function() { ... length = animation.tweens.length; for ( ; index < length ; index++ ) { animation.tweens[ index ].run( percent ); } ... }
看到?jīng)],每一個原子動畫有自己的run函數(shù)來執(zhí)行自己的動畫,這在創(chuàng)建緩動動畫組的時候就建好了的。
好了,整理一下動畫的整個核心流程:
1.先根據(jù)參數(shù)調(diào)用jQuery.speed獲取動畫相關(guān)參數(shù),得到一個類似如下的對象;并且生成動畫執(zhí)行函數(shù)doAnimation使用.queue壓入隊列并馬上執(zhí)行
opt = { complete: fnction(){...},//動畫執(zhí)行完成的回調(diào) duration: 400,//動畫執(zhí)行時長 easing: "swing",//動畫效果 queue: "fx",//動畫隊列 old: false/fnction(){...}, }
2.doAnimation中調(diào)用創(chuàng)建一個延時對象,使用延時對象的promise方法構(gòu)造一個動畫對象animation(延時對象+動畫特征列表),最后給animation添加動畫執(zhí)行完成后的回調(diào)函數(shù)。
3.調(diào)用jQuery內(nèi)部函數(shù)proFilter修正css特征名以便能被當前瀏覽器識別,并將某些復(fù)合css特征分解(比如padding分解成paddingTop / Right/ Bottom/ Left).
4.調(diào)用jQuery內(nèi)部函數(shù)defaultPrefilter做動畫能夠正常運行前提條件修正:比如對height/width動畫display和overflow需要特定的值。特別需要注意的是
對于show/hide動畫,在之前就調(diào)用genFx將需要執(zhí)行動畫的css特征提取了出來,在defaultPrefilter函數(shù)里直接調(diào)用動畫對象animation.createTween給每一個CSS動畫屬性添加對應(yīng)的緩動動畫對象(包括動畫參數(shù)和動畫函數(shù)如run)壓入緩動動畫組animation.tweens中
5.調(diào)用jQuery內(nèi)部函數(shù)createTweens將除開show/hide之外的動畫每一個css動畫特征使用animation.createTween創(chuàng)建緩動動畫對象(包括動畫參數(shù)和動畫函數(shù)如run),壓入緩動動畫組animation.tweens中
6.啟動動畫計時,在每個時間點上執(zhí)行tick函數(shù)來給相應(yīng)的css特征值設(shè)置運動值。
其中css特征值運動的進度百分比是
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), temp = remaining / animation.duration || 0, percent = 1 - temp
得到的percent是符合時間規(guī)律的。代入這個percent設(shè)置準確的css特征值,以刷新動畫顯示。
8.動畫完成后調(diào)用動畫完成回調(diào)。
關(guān)于小編給大家分享的jQuery 1.9.1源碼分析系列(十五)動畫處理之緩動動畫核心Tween 全部內(nèi)容就到此結(jié)束了,有問題歡迎給我留言我會在第一時間和大家取得聯(lián)系的。
- jQuery1.9.1針對checkbox的調(diào)整方法(prop)
- jQuery 1.9.1源碼分析系列(十)事件系統(tǒng)之綁定事件
- jQuery-1.9.1源碼分析系列(十)事件系統(tǒng)之事件體系結(jié)構(gòu)
- jQuery-1.9.1源碼分析系列(十)事件系統(tǒng)之事件包裝
- Jquery1.9.1源碼分析系列(六)延時對象應(yīng)用之jQuery.ready
- jQuery 1.9.1源碼分析系列(十三)之位置大小操作
- jQuery 1.9.1源碼分析系列(十四)之常用jQuery工具
- jQuery 1.9.1源碼分析系列(十五)之動畫處理
- Jquery1.9.1源碼分析系列(十五)動畫處理之外篇
相關(guān)文章
Jquery 監(jiān)視按鍵,按下回車鍵觸發(fā)某方法的實現(xiàn)代碼
這篇文章主要介紹了jquery監(jiān)視按鍵,當按下回車鍵時觸發(fā)事件的一個例子,有需要的朋友可以參考下2014-05-05flash+jQuery實現(xiàn)可關(guān)閉及重復(fù)播放的壓頂廣告
本文給大家分享的是仿游戲門戶網(wǎng)站可關(guān)閉及重復(fù)播放泰山壓頂廣告是一款基于jquery實現(xiàn)的打開網(wǎng)頁緩慢下拉廣告代碼。有需要的小伙伴可以參考下。2015-04-04jQuery實現(xiàn)高度靈活的表單驗證功能示例【無UI】
這篇文章主要介紹了jQuery實現(xiàn)高度靈活的表單驗證功能,涉及jQuery正則判斷與頁面元素動態(tài)操作相關(guān)使用技巧,需要的朋友可以參考下2020-04-04選擇TreeView控件的樹狀數(shù)據(jù)節(jié)點的JS方法(jquery)
前些日子為了提高人性化選擇樹狀權(quán)限的功能,根據(jù)樹的結(jié)構(gòu)用jquery寫了個方法。2010-02-02