• jQuery-1.9.1源码分析系列(十五) 动画处理——外篇


    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 = {};
    View Code

      这里其中执行动画的关键源码是

    //动画入口函数
    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 ); } };

      变量jQuery.timers = [];用来保存每次tick需要执行的函数列表。一般来说就只有一个函数,就是Animation函数中定义的tick函数。jQuery.fx.interval可以用来设置动画每两帧之间的时间间隔,默认为13毫秒。

      

      动画的分析就到这里。下面把动画相关的api列一下

    jQuery.fn.show([ duration ] [, easing ] [, complete ] | options )(显示所有匹配的元素。此外,你还可以指定元素显示的过渡动画效果。如果元素本身是可见的,则不对其作任何改变。如果元素是隐藏的,则使其可见。与该函数相对的是hide()函数,用于隐藏所有匹配的元素)

    jQuery.fn.hide([ duration ] [, easing ] [, complete ] | options)(隐藏所有匹配的元素。此外,你还可以指定元素隐藏的过渡动画效果。如果元素本身是不可见的,则不对其作任何改变。如果元素是可见的,则将其隐藏。)

    jQuery.fn.toggle([ duration ] [, easing ] [, complete ] | options)(切换所有匹配的元素。此外,你还可以指定元素切换的过渡动画效果。所谓"切换",也就是如果元素当前是可见的,则将其隐藏;如果元素当前是隐藏的,则使其显示(可见)。)

    这里介绍的toggle()函数用于切换元素的显示/隐藏。jQuery还有一个同名的事件函数toggle(),用于绑定click事件并在触发时轮流切换执行不同的事件处理函数。

    jQuery.fn.slideDown([ duration ] [, easing ] [, complete ] | options)显示所有匹配的元素,并带有向下滑动的过渡动画效果。向下滑动的动画效果,即元素可见区域的高度从0逐渐增大到其原有高度(向下逐渐展开)。如果元素本身是可见的,则不对其作任何改变。如果元素是隐藏的,则使其可见。

    与该函数相对的是slideUp()函数,用于隐藏所有匹配的元素,并带有向上滑动的过渡动画效果

    jQuery.fn.slideUp([ duration ] [, easing ] [, complete ] | options)隐藏所有匹配的元素,并带有向上滑动的过渡动画效果。向上滑动的动画效果,即元素可见区域的高度从原有高度逐渐减小到0(向上逐渐收起)。如果元素本身是隐藏的,则不对其作任何改变。如果元素是可见的,则将其隐藏)

    jQuery.fn.slideToggle([ duration ] [, easing ] [, complete ] | options)切换所有匹配的元素,并带有滑动的过渡动画效果。所谓"切换",也就是如果元素当前是可见的,则将其隐藏(向上滑动);如果元素当前是隐藏的,则使其显示(向下滑动))

    jQuery.fn.fadeIn([ duration ] [, easing ] [, complete ] | options)显示所有匹配的元素,并带有淡入的过渡动画效果。淡入的动画效果,即元素的不透明度的比例从0%逐渐增加到100%。如果元素本身是可见的,则不对其作任何改变。如果元素是隐藏的,则使其可见。与该函数相对的是fadeOut()函数,用于隐藏所有匹配的元素,并带有淡出的过渡动画效果)

    jQuery.fn.fadeOut([ duration ] [, easing ] [, complete ] | options)隐藏所有匹配的元素,并带有淡出的过渡动画效果。所谓"淡出"的动画效果,即元素的不透明度的比例从100%逐渐减小到0%。如果元素本身是隐藏的,则不对其作任何改变。如果元素是可见的,则将其隐藏)

    jQuery.fn.fadeToggle([ duration ] [, easing ] [, complete ] | options)切换所有匹配的元素,并带有淡入/淡出的过渡动画效果。所谓"切换",即如果元素当前是可见的,则将其隐藏(淡出);如果元素当前是隐藏的,则使其显示(淡入))

    jQuery.fn.animate(cssProperties [, duration ] [, easing ] [, complete ] | cssProperties, options)执行一个基于css属性的自定义动画。你可以为匹配的元素设置css样式,animate()函数将会执行一个从当前样式到指定的css样式的一个过渡动画。例如:某个div元素的当前高度为100px,将其CSS height属性设为200px,animate()将会执行一个将div元素的高度从100px逐渐增加到200px的过渡动画)

    jQuery.fn.delay(duration [, queueName ])延迟队列中下一项的执行。delay()可以将队列中等待执行的下一个动画延迟指定的时间后才执行。它常用在队列中的两个jQuery效果函数之间,从而在上一个动画效果执行后延迟下一个动画效果的执行时间。如果下一项不是效果动画,则它不会被加入效果队列中,因此该函数不会对它进行延迟调用)

    jQuery.fn.stop([ queueName ] [, clearQueue [, jumpToEnd ] ])停止当前匹配元素上正在运行的动画。默认情况下,stop()函数只会停止当前正在运行的动画。如果你使用animate()函数为当前元素设置了A、B、C这3段动画,如果当前正在执行的动画是A,则只会停止动画A的执行,不会阻止动画B和C的执行。当然,你也可以通过指定可选的选项参数来停止所有的动画。停止动画并不是恢复到该动画执行前的状况,而是直接停止,当前动画执行到什么状态,就停留在什么状态。例如:执行一个元素高度从100px到200px的过渡动画,当高度为150px时停止了该动画,则当前高度仍然保持150px的现状。如果该动画设置了执行完毕后的回调函数,则不会执行该回调函数。)

    jQuery.fn.finish([ queueName ])立即完成队列中的所有动画finish()会停止当前正在运行的动画,删除所有队列中的动画,并完成匹配元素的所有动画)

    jQuery.fn. fadeTo([speed,]opacity[,callback])(将被选元素的不透明度逐渐地改变为指定的值)

    jQuery.fx.off(该属性用于设置或返回是否全局性地禁用所有动画。如果不对该属性设置值,则返回表示是否全局性地禁用了动画效果的布尔值。如果将该属性设为true,将全局性地禁用所有动画。所有正在执行的动画队列不会受到影响。尚未执行的任何动画队列都会在执行时立即完成,而不再带有动画效果。如果将该属性设为false,将全局性地启用动画效果。

    你可以在遇到以下情况时,需要禁用动画效果:你在配置比较低的电脑上使用jQuery;某些用户可能由于动画效果而遇到了可访问性问题。)

    jQuery.fx.interval(该属性用于设置或返回动画的帧速(毫秒值)。jQuery.fx.interval属性用于设置jQuery动画每隔多少毫秒绘制一帧图像(触发一次样式更改,浏览器可能会重新绘制当前页面)。该值越小,则动画的触发次数越多,动画效果也更明显、更平滑,当然也就越耗费性能。更改该属性值时,正在执行的动画队列将不受影响。尚未执行的任何动画队列都将按照更改后的帧速来绘制动画效果)

      

  • 相关阅读:
    管理中的“变”与“不变”
    软件项目需求分析与管理的十大疑问
    小商家也要有O2O思维
    互联网时代CIO生存法则
    浅谈项目经理与部门经理之间的关系
    沃尔玛:“最后一公里”的致命伤
    大数据分析案例:永远别忘记天气这个变量
    IT项目中的6类知识转移
    C
    linu入门
  • 原文地址:https://www.cnblogs.com/chuaWeb/p/jQuery-1-9-1-animate-3.html
Copyright © 2020-2023  润新知