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