a.動畫兼容Tween.propHooks
Tween.propHooks提供特殊情況下設置、獲取css特征值的方法,結構如下
Tween.propHooks = { _default: { get: function(){...}, set: function(){...} }, scrollTop: { set: function(){...} } scrollLeft: { set: function(){...} }}
Tween.propHooks.scrollTop 和Tween.propHooks.scrollLeft兩個主要是在ie8離線狀態下會出現混亂而把css特征值保存到節點上
set: function( tween ) { if ( tween.elem.nodeType && tween.elem.parentNode ) { tween.elem[ tween.prop ] = tween.now; }}
Tween.propHooks._default的get方法會嘗試直接從節點上取得css的tween.prop特征值,如果取不到則使用jQuery.css()方式來獲取。該方法處理中,簡單的值如“10px”會被解析為浮點數;復雜的值,如“旋轉(1rad)”返回原樣。并對返回結果再做處理:空字符串, null, undefined 和 "auto"都轉化為0;其他情況不變。
get: function( tween ) { var result; if ( tween.elem[ tween.prop ] != null && (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { return tween.elem[ tween.prop ]; } //傳遞一個空字符串作為第三個參數的.css會自動嘗試parseFloat, //并返回到一個字符串,如果解析失敗的話。 //所以,簡單的值,如“10px”會被被解析為浮點數。復雜的值,如“旋轉(1rad)”返回原樣。 result = jQuery.css( tween.elem, tween.prop, "" ); // 空字符串, null, undefined 和 "auto"都轉化為0 return !result || result === "auto" ? 0 : result;}
Tween.propHooks._default的set方法先會嘗試jQuery.fx.step[ tween.prop ]來設置向下兼容;否則會使用jQuery.style來設置css特征值;最極端情況則會將特征值直接保存在節點上
set: function( tween ) { //使用step hook向下兼容 - 使用cssHook如果他存在 - 使用.style如果可用的話 //使用直接的特征值如果可用可用的話 if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; }}
b. 動畫專用對象jQuery.fx
jQuery.fx封裝了一些用來執行動畫動作的函數,結構如下
jQuery.fx = { tick = function () {...},//每個時間點都會執行的函數外殼,會取出jQuery.timers中的函數執行 timer = function ( timer ) {...},//執行參數中的函數并啟動計時 interval = 13, //計時步長 start = function () {...},//啟動計時 stop = function () {...},//停止計時 speeds = {slow: 600,fast: 200,_default: 400},//動畫速度(完整動畫執行時間) step = {}//向下兼容<1.8擴展點}
詳細的源碼分析如下
jQuery.fx = Tween.prototype.init;//每個時間點都會執行的函數外殼,會取出jQuery.timers中的函數執行jQuery.fx.tick = function() { var timer, timers = jQuery.timers, i = 0; fxNow = jQuery.now(); for ( ; i < timers.length; i++ ) { timer = timers[ i ]; // Checks the timer has not already been removed if ( !timer() && timers[ i ] === timer ) { timers.splice( i--, 1 ); } } if ( !timers.length ) { jQuery.fx.stop(); } fxNow = undefined;};//執行參數中的函數并啟動計時jQuery.fx.timer = function( timer ) { if ( timer() && jQuery.timers.push( timer ) ) { jQuery.fx.start(); }};//計時步長jQuery.fx.interval = 13;//啟動計時jQuery.fx.start = function() { if ( !timerId ) { timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); }};//停止計時jQuery.fx.stop = function() { clearInterval( timerId ); timerId = null;};//動畫速度(完整動畫執行時間)jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400};//向下兼容<1.8擴展點jQuery.fx.step = {}; 這里其中執行動畫的關鍵源碼是//動畫入口函數function Animation( elem, properties, options ){ ... jQuery.fx.timer( jQuery.extend( tick, { elem: elem, anim: animation, queue: animation.opts.queue }) ); ...}//執行參數中的函數并啟動計時jQuery.fx.timer = function( timer ) { if ( timer() && jQuery.timers.push( timer ) ) { jQuery.fx.start(); }};//計時步長jQuery.fx.interval = 13;//啟動計時jQuery.fx.start = function() { if ( !timerId ) { timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); }};
新聞熱點
疑難解答
圖片精選