• jQuery源码学习11——动画


    jQuery.setAuto这个方法实在看不出来到底有啥用,而且到后面的版本就把这个方法去掉了

    直接看speed方法

    jQuery.extend({
        speed: function(s,o) {
            o = o || {};
            
            if ( o.constructor == Function )
                o = { complete: o };
            
            var ss = { slow: 600, fast: 200 };
            o.duration = (s && s.constructor == Number ? s : ss[s]) || 400;
        
            // Queueing
            o.oldComplete = o.complete;
            o.complete = function(){
                jQuery.dequeue(this, "fx");
                if ( o.oldComplete && o.oldComplete.constructor == Function )
                    o.oldComplete.apply( this );
            };
        
            return o;
        }
    });

    从名字上看很容易知道这是控制速度的一个方法

    从源码中看,在animate方法中通过jQuery.speed(speed,callback)调用了一次

    speed方法最终会构造一个json形式的config,结构如下:

        {
            duration:400,//持续时间
            oldComplete:function(){
                ...//自定义的函数
            },
            complete:function(){
                jQuery.dequeue(this, "fx");
                if ( o.oldComplete && o.oldComplete.constructor == Function )
                    o.oldComplete.apply( this );
            }
        }

    调用complete时里面的this指向一定有变化,所以等分析到调用complete的时候再看

    接下来的dequeue方法也一样,从字面上来看就是出队的意思

    再往下的fx方法是核心

        jQuery.extend(    
            fx: function( elem, options, prop ){
                var z = this;
                z.o = {...};
                z.el = elem;
                z.a = function(){...};
                z.max = function(){...};
                z.cur = function(){...};
                z.custom = function(from,to){...};
                z.show = function( p ){...};
                z.hide = function(){...};
                z.step = function(firstNum, lastNum){...};    
            }
        );

    实际上,jQuery.fx在源码中被用作构造方法,从animate实力方法中发现通过new jQuery.fx()来调用了

    z就是new出来的对象,然后往对象上扩展了很多方法

    构造方法里面的各个方法之间相互调用,因此比较复杂,我们通过一个例子来看

    $("#div1").animate({"width":500},1000,function(){alert("over");});

    意思就是让#div1在1s时间内宽变到500,完了之后弹出over

    1、queue

    调用形式为this.queue(function(){...});

        queue: function(type,fn){
            if ( !fn ) {
                fn = type;
                type = "fx";
            }
        
            return this.each(function(){//此处的this是jQuery对象
                if ( !this.queue )
                    this.queue = {};
        
                if ( !this.queue[type] )
                    this.queue[type] = [];
                //以上代码是给jQuery对象里面的每个DOM元素都附加queue这个属性,queue下将会按照队列的类型来存放函数
                this.queue[type].push( fn );
                //如果当前type类型的队列里面只有一个函数,就直接执行,而且这个函数内部的this更改为了each每次遍历到的DOM对象
                if ( this.queue[type].length == 1 )
                    fn.apply(this);
            });
        }

     2、执行传入this.queue里面的函数

        animate: function(prop,speed,callback) {
            return this.queue(function(){
            
                this.curAnim = prop;//this指向queue中遍历到的DOM对象,prop形如
                /*{
                    "width":500,
                    "opacity":50,
                    "height":200
                }*/
                
                for ( var p in prop ) {
                    var e = new jQuery.fx( this, jQuery.speed(speed,callback), p );
                    if ( prop[p].constructor == Number )
                //custom的两个参数分别是起始值和目标值 e.custom( e.cur(), prop[p] );
    else//暂时搞不太清楚什么时候走else这个分支 e[ prop[p] ]( prop ); } }); },

    3、cur custom

            //得到elem当前prop的值
            z.cur = function(){
                var r = parseFloat( jQuery.curCSS(z.el, prop) );
                return r && r > -10000 ? r : z.max();
            };
            //在当前实例化对象上绑定startTime、now属性,now存储的是最初从哪个值开始动,startTime和now这两个属性为接下来执行的a和step做了铺垫
            z.custom = function(from,to){
                z.startTime = (new Date()).getTime();
                z.now = from;
                z.a();
        
                z.timer = setInterval(function(){
                    z.step(from, to);
                }, 13);
            };

    4、a

            z.a = function(){
                //目前很明显options里面只有complete、oldComplete、duration三个属性,没有step
                if ( options.step )
                    options.step.apply( elem, [ z.now ] );
                //当改变的样式是透明度时,对于IE浏览器要做特殊处理
                if ( prop == "opacity" ) {
                    if (z.now == 1) z.now = 0.9999;
                    if (window.ActiveXObject)
                        y.filter = "alpha(opacity=" + z.now*100 + ")";
                    else
                        y.opacity = z.now;
                } else if ( parseInt(z.now) )
                    //如果运动形式不是opacity,就直接按照数字处理
                    y[prop] = parseInt(z.now) + "px";
                    
                y.display = "block";
            };

    5、step

    这个step方法每隔13毫秒就会调用一次

    step先获取当前调用step的时间戳

    再判断是否到达了目的值

    如果没到目的值,递增或递减z.now的值,并再次执行z.a将递增或递减后的值赋给DOM元素

    如果到达目的值了就停掉定时器,然后判断别运动的样式是否到目的值,如果全都到了就再去做一系列后续操作,执行结束的回调函数

  • 相关阅读:
    AlphaToCoverage solution
    PhyreEngine3.8 MSAA resolution
    渲染错误
    tomcat
    Jupyter
    Flask
    Highcharts20151130
    CodeMirror
    响应式
    import
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/5007430.html
Copyright © 2020-2023  润新知