国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

jQuery源碼解析之$().animate()(下)

raledong / 2190人閱讀

摘要:根據(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)元素
  //{"width": "500"}
  // optall={
  //   complete:function(){jQuery.dequeue()},
  //   old:false,
  //   duration: 400,
  //   easing: undefined,
  //   queue:"fx",
  // }

  function Animation( elem, properties, options ) {
    var result,
      stopped,
      index = 0,
      //1
      length = Animation.prefilters.length,
      //{
      // always:function(){},
      // catch:function(){},
      // done:function(){},
      // xxx
      // }

      //初始化deferred對(duì)象
      //deferred.always()表示不管成功還是失敗,最終都會(huì)運(yùn)行內(nèi)部設(shè)置的代碼
      deferred = jQuery.Deferred().always( function() {

        // Don"t match elem in the :animated selector
        delete tick.elem;
      } ),
      
      tick = function() {
        if ( stopped ) {
          return false;
        }
        var currentTime = fxNow || createFxNow(),
          remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),

          // Support: Android 2.3 only
          // Archaic crash bug won"t allow us to use `1 - ( 0.5 || 0 )` (#12497)
          temp = remaining / animation.duration || 0,
          percent = 1 - temp,
          index = 0,
          length = animation.tweens.length;

        for ( ; index < length; index++ ) {
          animation.tweens[ index ].run( percent );
        }

        deferred.notifyWith( elem, [ animation, percent, remaining ] );

        // If there"s more to do, yield
        if ( percent < 1 && length ) {
          return remaining;
        }

        // If this was an empty animation, synthesize a final progress notification
        if ( !length ) {
          deferred.notifyWith( elem, [ animation, 1, 0 ] );
        }

        // Resolve the animation and report its conclusion
        deferred.resolveWith( elem, [ animation ] );
        return false;
      },
      //==========tick end==========
      //讓animation帶有promise的屬性,并在其中添加動(dòng)畫的屬性和方法
      animation = deferred.promise( {
        elem: elem,
        props: jQuery.extend( {}, properties ),
        opts: jQuery.extend( true, {
          specialEasing: {},
          easing: jQuery.easing._default
        }, options ),
        originalProperties: properties,
        originalOptions: options,
        startTime: fxNow || createFxNow(),
        duration: options.duration,
        tweens: [],
        //500,"width",animation
        createTween: function( prop, end ) {
          var tween = jQuery.Tween( elem, animation.opts, prop, end,
            animation.opts.specialEasing[ prop ] || animation.opts.easing );
          animation.tweens.push( tween );
          // {
          //   easing: "swing"
          //   elem: div#A
          //   end: 500
          //   now: 500
          //   options: {specialEasing: {…}, easing: "swing", complete: ?, duration: 400, queue: "fx", …}
          //   pos: 1
          //   prop: "width"
          //   start: 100
          //   unit: "px"
          // }
          return tween;
        },
        stop: function( gotoEnd ) {
          var index = 0,

            // If we are going to the end, we want to run all the tweens
            // otherwise we skip this part
            length = gotoEnd ? animation.tweens.length : 0;
          if ( stopped ) {
            return this;
          }
          stopped = true;
          for ( ; index < length; index++ ) {
            animation.tweens[ index ].run( 1 );
          }

          // Resolve when we played the last frame; otherwise, reject
          if ( gotoEnd ) {
            deferred.notifyWith( elem, [ animation, 1, 0 ] );
            deferred.resolveWith( elem, [ animation, gotoEnd ] );
          } else {
            deferred.rejectWith( elem, [ animation, gotoEnd ] );
          }
          return this;
        }
      } ),
      //===========animation end===============
      props = animation.props;
    //{width:500},undefined
    propFilter( props, animation.opts.specialEasing );

    for ( ; index < length; index++ ) {
      result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
      if ( result ) {
        if ( isFunction( result.stop ) ) {
          jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
            result.stop.bind( result );
        }
        return result;
      }
    }
    /*運(yùn)行動(dòng)畫*/
    // createTween(500,"width",animation)
    jQuery.map( props, createTween, animation );

    if ( isFunction( animation.opts.start ) ) {
      animation.opts.start.call( elem, animation );
    }

    // Attach callbacks from options
    animation
      .progress( animation.opts.progress )
      .done( animation.opts.done, animation.opts.complete )
      .fail( animation.opts.fail )
      .always( animation.opts.always );

    jQuery.fx.timer(
      //讓tick方法繼承elem、anim和queue屬性
      jQuery.extend( tick, {
        elem: elem,
        anim: animation,
        queue: animation.opts.queue
      } )
    );

    return animation;
  }

解析:

(1)Animation.prefilters
源碼:

jQuery.Animation = jQuery.extend( Animation, {
    //源碼8175行
    //defaultPrefilter是一個(gè)function
    prefilters: [ defaultPrefilter ],
})

所以Animation.prefilters=1defaultPrefilter的源碼暫不解析

(2)關(guān)于jQuery.Deferred()的解釋,請(qǐng)參考:jQuery中的Deferred詳解和使用

(3)jQuery.map(elems, callback, arg)
作用:
根據(jù)elems數(shù)量,循環(huán)運(yùn)行callback( elems[ i ], i, arg )

源碼:

jQuery.extend( {
    // arg is for internal usage only
    //源碼524行
    //props, createTween, animation
    map: function( elems, callback, arg ) {
      var length, value,
        i = 0,
        ret = [];

      // Go through the array, translating each of the items to their new values
      //如果elems是類數(shù)組的話
      if ( isArrayLike( elems ) ) {
        length = elems.length;
        for ( ; i < length; i++ ) {
          value = callback( elems[ i ], i, arg );

          if ( value != null ) {
            ret.push( value );
          }
        }

        // Go through every key on the object,
      } else {
        //走這邊
        for ( i in elems ) {
          //500 width animation
          /*執(zhí)行動(dòng)畫*/
          value = callback( elems[ i ], i, arg );

          if ( value != null ) {
            ret.push( value );
          }
        }
      }
      console.log(ret,"ret555")
      // Flatten any nested arrays
      // 展平任何嵌套數(shù)組
      return concat.apply( [], ret );
    },

})

解析:
根據(jù)例子的話,就是:

createTween(500,"width",animation)
createTween(300,"width",animation)
createTween(1000,"width",animation)

(4)jQuery內(nèi)部函數(shù)createTween(value, prop, animation)
作用:
animation調(diào)用Animation.tweeners[ "*" ]中的方法

源碼:

  //源碼7752行
  //創(chuàng)建動(dòng)畫對(duì)象
  // createTween(500,"width",animation)
  function createTween( value, prop, animation ) {
    var tween,
      //[ function( prop, value ) {
      //         var tween = this.createTween( prop, value );
      //         console.log("vvvv","aaa8083")
      //         adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
      //         return tween;
      //       } ]
      collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
      index = 0,
      //1
      length = collection.length;
    for ( ; index < length; index++ ) {
      //prop:width
      //value:500
      //運(yùn)行collection[ index ],this綁定animation
      if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {

        // We"re done with this property
        return tween;
      }
    }
  }

(5)Animation.tweeners[ "*" ]
作用:
animation調(diào)用Animation.tweeners[ "*" ]中的方法

  jQuery.Animation = jQuery.extend( Animation, {
    //源碼8152行
    tweeners: {
      //prop:width
      //value:500
      "*": [ function( prop, value ) {
        //animation.createTween
        var tween = this.createTween( prop, value );
        adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
        return tween;
      } ]
    },

})

解析:
返回經(jīng)過animation. createTween("width",500)處理和adjustCSS()處理的變量tween

① animation. createTween("width",500)
animationAnimation()方法中封裝的一個(gè)對(duì)象(對(duì)象keyvaluefunction

作用:
根據(jù)開發(fā)者傳入的屬性,將其轉(zhuǎn)化為一個(gè)對(duì)象,對(duì)象內(nèi)部的屬性時(shí)執(zhí)行動(dòng)畫所需要的屬性。

源碼:

animation = deferred.promise( {
   //500,"width",animation
   createTween: function( prop, end ) {
      var tween = jQuery.Tween( elem, animation.opts, prop, end,
          animation.opts.specialEasing[ prop ] || animation.opts.easing );
          animation.tweens.push( tween );
          // {
          //   easing: "swing"
          //   elem: div#A
          //   end: 500
          //   now: 500
          //   options: {specialEasing: {…}, easing: "swing", complete: ?, duration: 400, queue: "fx", …}
          //   pos: 1
          //   prop: "width"
          //   start: 100
          //   unit: "px"
          // }
          return tween;
      },
})

解析:
調(diào)用jQuery.Tween獲得tween對(duì)象,并把tween對(duì)象放進(jìn)animation.tweens數(shù)組中

② 簡單看下jQuery.Tween源碼:

  //源碼7568行
  function Tween( elem, options, prop, end, easing ) {
    //width 500 swing
    //width 300 swing
    //width 1000 swing
    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 || jQuery.easing._default;
      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;

執(zhí)行jQuery.Tween方法,就是new一個(gè)對(duì)象,就是執(zhí)行jQuery.Tween.init()方法,根據(jù){width:500}生成的動(dòng)畫對(duì)象如下:

{
  easing: "swing"
  elem: div#A
  end: 500
  now: 500
  options: {specialEasing: {…}, easing: "swing", complete: ?, duration: 400, queue: "fx", …}
   pos: 1
   prop: "width"
   start: 100
   unit: "px"
}

③ 關(guān)于adjustCSS的解析,請(qǐng)看:jQuery源碼解析(4)—— css樣式、定位屬性

Animation.tweeners[ "*" ]方法最終返回的tween如下:

{
  easing: "swing"
  elem: div#A
  end: 500
  now: 500
  options: {specialEasing: {…}, easing: "swing", complete: ?, duration: 400, queue: "fx", …}
   pos: 1
   prop: "width"
   start: 100
   unit: "px"
}

綜上,jQuery.map()最終作用就是將$().animate()中的參數(shù)轉(zhuǎn)化為動(dòng)畫對(duì)象,并push進(jìn)animation.tweens數(shù)組中

(6)jQuery.fx.timer()
作用:
依次執(zhí)行timer

源碼:

  //源碼8504行
  //單個(gè)動(dòng)畫內(nèi)部執(zhí)行
  jQuery.fx.timer = function( timer ) {
    //將Animation.tick()依次放進(jìn)jQuery.timers數(shù)組中
    jQuery.timers.push( timer );
    //每push進(jìn)一個(gè),就運(yùn)行一個(gè)
    jQuery.fx.start();
  };

jQuery.timers是一個(gè)數(shù)組:

//源碼8431行
  jQuery.timers = [];

(7)jQuery.fx.start()
作用:
在動(dòng)畫運(yùn)行前,加鎖,并運(yùn)行動(dòng)畫

源碼:

  //源碼8514行
  //加鎖,運(yùn)行動(dòng)畫
  jQuery.fx.start = function() {
    if ( inProgress ) {
      return;
    }
    //動(dòng)畫開始即為運(yùn)行中,加上鎖
    inProgress = true;
    //運(yùn)行
    schedule();
  };

注意:inProgress 鎖是控制整個(gè)動(dòng)畫流程的鎖,而不是單個(gè)動(dòng)畫隊(duì)列的鎖

(8)schedule()
作用:
如果動(dòng)畫已經(jīng)開始(inProgress=true),那么就不斷執(zhí)行jQuery.fx.tick()方法(動(dòng)畫渲染)

源碼:

  //源碼7694行
  //如果動(dòng)畫已經(jīng)開始,那么就不斷執(zhí)行jQuery.fx.tick()方法(動(dòng)畫渲染)
  function schedule() {
    //inProgress是判斷整個(gè)動(dòng)畫流程是否結(jié)束的標(biāo)志
    //當(dāng)inProgress=null時(shí),整個(gè)動(dòng)畫結(jié)束
    if ( inProgress ) {
      //走這邊
      if ( document.hidden === false && window.requestAnimationFrame ) {
        //使用requestAnimationFrame來完成動(dòng)畫
        //遞歸
        window.requestAnimationFrame( schedule );
      } else {
        //13代表動(dòng)畫每秒運(yùn)行的幀數(shù),可以保證瀏覽器能完成動(dòng)畫
       //jQuery.fx.interval = 13;
        window.setTimeout( schedule, jQuery.fx.interval );
      }
      /*執(zhí)行動(dòng)畫*/
      jQuery.fx.tick();
    }
  }

(9)jQuery.fx.tick()
作用:
運(yùn)行Animation.tick()并安全地移除它

源碼:

  //源碼8483行
  //運(yùn)行Animation.tick()并安全地移除它
  jQuery.fx.tick = function() {
    var timer,
      i = 0,
      timers = jQuery.timers;

    fxNow = Date.now();
    //這里的timers,就是Animation.tick()的集合
    for ( ; i < timers.length; i++ ) {
      timer = timers[ i ];

      // Run the timer and safely remove it when done (allowing for external removal)
      //運(yùn)行Animation.tick()并安全地移除它
      if ( !timer() && timers[ i ] === timer ) {
        timers.splice( i--, 1 );
      }
    }
    //inProgress=null,停止動(dòng)畫
    if ( !timers.length ) {
      jQuery.fx.stop();
    }
    fxNow = undefined;
  };

  //源碼8474行
  //結(jié)束整個(gè)動(dòng)畫流程
  jQuery.fx.stop = function() {
    inProgress = null;
  };

(10)Animation.tick()
作用:
根據(jù)動(dòng)畫的參數(shù)來執(zhí)行動(dòng)畫

源碼:

function Animation( elem, properties, options ) {
//根據(jù)動(dòng)畫的參數(shù)來執(zhí)行動(dòng)畫
      tick = function() {
        if ( stopped ) {
          return false;
        }
        //當(dāng)前時(shí)間的時(shí)間戳
        var currentTime = fxNow || createFxNow(),
          //動(dòng)畫時(shí)長默認(rèn)400ms
          //開始時(shí)間+動(dòng)畫時(shí)長-當(dāng)前時(shí)間
          //在每次調(diào)用requestAnimationFrame后,記錄下剩下的的時(shí)間在總時(shí)間(duration)中的位置
          remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),

          // Support: Android 2.3 only
          // Archaic crash bug won"t allow us to use `1 - ( 0.5 || 0 )` (#12497)
          //剩下的時(shí)間占總時(shí)長的占比
          temp = remaining / animation.duration || 0,
          //當(dāng)前時(shí)間占總時(shí)長的占比
          percent = 1 - temp,
          index = 0,
          length = animation.tweens.length;

        for ( ; index < length; index++ ) {
          //根據(jù)傳入的動(dòng)畫參數(shù)和當(dāng)前進(jìn)程的百分比來運(yùn)行動(dòng)畫
          animation.tweens[ index ].run( percent );
        }

        deferred.notifyWith( elem, [ animation, percent, remaining ] );

        // If there"s more to do, yield
        if ( percent < 1 && length ) {
          return remaining;
        }

        // If this was an empty animation, synthesize a final progress notification
        if ( !length ) {
          deferred.notifyWith( elem, [ animation, 1, 0 ] );
        }

        // Resolve the animation and report its conclusion
        deferred.resolveWith( elem, [ animation ] );
        return false;
      },

}

解析:
通過動(dòng)畫持續(xù)時(shí)間duration、動(dòng)畫開始時(shí)間animation.startTime和每次調(diào)用requestAnimationFrame后動(dòng)畫結(jié)束時(shí)間currentTime,計(jì)算出此幀在整個(gè)動(dòng)畫流程中的占比,從而較為準(zhǔn)確繪制動(dòng)畫

(11)Tween.run()
作用:
繪制動(dòng)畫幀

源碼:

  Tween.prototype = {
      run: function( percent ) {
      // {
      //   easing: "swing"
      //   elem: div#A
      //   end: 500
      //   now: 105.52601592046467
      //   options: {specialEasing: {…}, easing: "swing", complete: ?, duration: 400, queue: "fx", …}
      //   pos: 1
      //   prop: "width"
      //   start: 100
      //   unit: "px"
      // }
      var eased,
        //undefiend
        hooks = Tween.propHooks[ this.prop ];
      //400
      if ( this.options.duration ) {
        //swing,兩邊慢中間快
        //動(dòng)畫效果
        this.pos = eased = jQuery.easing[ this.easing ](
          percent, this.options.duration * percent, 0, 1, this.options.duration
        );
      } else {
        this.pos = eased = percent;
      }
      //width的寬度
      this.now = ( this.end - this.start ) * eased + this.start;

      if ( this.options.step ) {
        this.options.step.call( this.elem, this.now, this );
      }

      if ( hooks && hooks.set ) {
        hooks.set( this );
      } else {
        //走這邊
        //執(zhí)行style變化
        Tween.propHooks._default.set( this );
      }
      return this;
    },

  }

解析:
一個(gè)是動(dòng)畫效果swing的處理:jQuery.easing[ this.easing ](percent, this.options.duration * percent, 0, 1, this.options.duration);

另一個(gè)就是關(guān)鍵style變化了:Tween.propHooks._default.set( this )

(12)Tween.propHooks._default.set()
作用:
執(zhí)行style變化

源碼:

  Tween.propHooks = {
    _default: {
      //源碼7661行
      set: function( tween ) {  
        // Use step hook for back compat.
        // Use cssHook if its there.
        // Use .style if available and use plain properties where available.
        //undefined
        if ( jQuery.fx.step[ tween.prop ] ) {
          jQuery.fx.step[ tween.prop ]( tween );
        } else if ( tween.elem.nodeType === 1 &&
          ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
            jQuery.cssHooks[ tween.prop ] ) ) {
          //走這邊
          //#A,width,100px(103px,134px,xxx)
          jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
        } else {
          tween.elem[ tween.prop ] = tween.now;
        }
      },

  }
}

解析:
tween.now,是每次requestAnimationFrame要變化的width的值,tween.unitpx,所以這段代碼最終執(zhí)行的是jQuery.style( 目標(biāo)元素, 要變化的style屬性, 要變化的值 )

(13)jQuery.style()
作用:
設(shè)置 DOM 節(jié)點(diǎn)的 style 屬性

簡略的源碼:

    // Get and set the style property on a DOM Node
    //源碼7279行
    style: function( elem, name, value, extra ) {
         elem.style[ name ] = value
    }

綜上,Animation() 有兩大作用:
(1)將傳入的動(dòng)畫對(duì)象處理成jQuery的動(dòng)畫對(duì)象。
(2)根據(jù)duration的間隔,利用requestAnimationFrame循環(huán)執(zhí)行style,從而達(dá)到渲染動(dòng)畫的目的。

最后,附上 doAnimation() 的流程圖,建議配合整個(gè)$().animate()的流程圖(二、的最后一個(gè)圖)一起看:

下篇將會(huì)模擬實(shí)現(xiàn)$().animate() 方法,敬請(qǐng)期待!

(完)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105056.html

相關(guān)文章

  • jQuery源碼解析$().animate()(上)

    摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調(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í)行 showImg(https://segmentfault.com/img/remote/1460000019594521); 前言:需要先看 jQue...

    Batkid 評(píng)論0 收藏0
  • jQuery模擬實(shí)現(xiàn)$().animate()(

    摘要:前言在上篇的基礎(chǔ)上,接入邏輯圖實(shí)現(xiàn)之的實(shí)現(xiàn)這是匿名函數(shù)自調(diào)用,下面好長好長的就是也就是說是一個(gè)這里也是匿名函數(shù)自調(diào)用本質(zhì)就是經(jīng)過一系列操作得到并作為參數(shù),賦值給匹配初始化模仿動(dòng)畫效果兩頭慢,中間快創(chuàng)建動(dòng)畫緩動(dòng)對(duì)象動(dòng)畫緩動(dòng)算法 showImg(https://segmentfault.com/img/remote/1460000019626160); 前言:在上篇的基礎(chǔ)上,接入doAni...

    Coding01 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

raledong

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<