• jquery fx 源码


    1. /*  
    2.  * author:prk date:2008-08-07 comment:analyse the fx of jQuery.  
    3.  *   
    4.  */  
    5. jQuery.fn.extend({   
    6.        
    7.     // show(speed,[callback])   
    8.     // 以优雅的动画隐藏所有匹配的元素,并在显示完成后可选地触发一个回调函数。   
    9.     // 可以根据指定的速度动态地改变每个匹配元素的高度、宽度和不透明度。   
    10.     // 显示隐藏的匹配元素 show()   
    11.     show: function(speed,callback){   
    12.         return speed ?   
    13.             this.animate({   
    14.                 height: "show",  "show", opacity: "show"  
    15.             }, speed, callback) :   
    16.   
    17.             this.filter(":hidden").each(function(){   
    18.                 this.style.display = this.oldblock || "";   
    19.                 if ( jQuery.css(this,"display") == "none" ) {   
    20.                     var elem = jQuery("<" + this.tagName + " />").appendTo("body");   
    21.                     this.style.display = elem.css("display");// 默认的显示的display   
    22.                     // handle an edge condition where css is - div {   
    23.                     // display:none; } or similar   
    24.                     if (this.style.display == "none")// 处理显式地设定了该tag不显示,只好采用b   
    25.                         this.style.display = "block";   
    26.                     elem.remove();// 上面这些的处理有没有必要呢?   
    27.                 }   
    28.             }).end();// 回到前一个jQuery对象   
    29.     },   
    30.        
    31.     // 与show相反   
    32.     hide: function(speed,callback){   
    33.         return speed ?   
    34.             this.animate({   
    35.                 height: "hide",  "hide", opacity: "hide"  
    36.             }, speed, callback) :   
    37.   
    38.             this.filter(":visible").each(function(){   
    39.                 this.oldblock = this.oldblock || jQuery.css(this,"display");   
    40.                 this.style.display = "none";   
    41.             }).end();   
    42.     },   
    43.   
    44.     // Save the old toggle function   
    45.     _toggle: jQuery.fn.toggle,   
    46.         
    47.     // 切换元素的可见状态。   
    48.     // 如果元素是可见的,切换为隐藏的;如果元素是隐藏的,切换为可见的。   
    49.        
    50.     // 每次点击后依次调用函数。   
    51.     // 如果点击了一个匹配的元素,则触发指定的第一个函数,当再次点击同一元素时,则触发指定的第二个函数,   
    52.     // 如果有更多函数,则再次触发,直到最后一个。随后的每次点击都重复对这几个函数的轮番调用。   
    53.     // 可以使用unbind("click")来删除。   
    54.     toggle: function( fn, fn2 ){   
    55.         return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?   
    56.             this._toggle.apply( this, arguments ) :// 原来的toggle   
    57.             (fn ?   
    58.                this.animate({height: "toggle",  "toggle", opacity: "toggle"}, fn, fn2)   
    59.             :  this.each(function(){jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();}   
    60.             // 对每个元素都调用show,或hide函数。   
    61.             )   
    62.         );   
    63.     },   
    64.   
    65.     // 把所有匹配元素的不透明度以渐进方式调整到指定的不透明度,并在动画完成后可选地触发一个回调函数。   
    66.      // 这个动画只调整元素的不透明度,也就是说所有匹配的元素的高度和宽度不会发生变化。   
    67.     fadeTo: function(speed,to,callback){   
    68.         return this.animate({opacity: to}, speed, callback);   
    69.     },   
    70.        
    71.     /**  
    72.      * 用于创建自定义动画的函数。  
    73.      * 这个函数的关键在于指定动画形式及结果样式属性对象。这个对象中每个属性都表示一个可以变化的样式属性(如“height”、“top”或“opacity”)。  
    74.      * 注意:所有指定的属性必须用骆驼形式,比如用marginLeft代替margin-left.  
    75.      * 而每个属性的值表示这个样式属性到多少时动画结束。如果是一个数值,样式属性就会从当前的值渐变到指定的值。如果使用的是“hide”、“show”或“toggle”这样的字符串值,则会为该属性调用默认的动画形式。  
    76.      * 在 jQuery 1.2 中,你可以使用 em 和 % 单位。另外,在 jQuery 1.2 中,你可以通过在属性值前面指定 "+=" 或  
    77.      * "-=" 来让元素做相对运动。  
    78.      *   
    79.      * params (Options) : 一组包含作为动画属性和终值的样式属性和及其值的集合 。 duration (String,Number)  
    80.      * :(可选) 三种预定速度之一的字符串("slow", "normal", or "fast")或表示动画时长的毫秒数值(如:1000)  
    81.      * easing (String) : (可选) 要使用的擦除效果的名称(需要插件支持).默认jQuery提供"linear" 和 "swing".  
    82.      * callback (Function) : (可选) 在动画完成时执行的函数  
    83.      */  
    84.     animate: function( prop, speed, easing, callback ) {   
    85.         var optall = jQuery.speed(speed, easing, callback);   
    86.   
    87.         return this[ optall.queue === false ? "each" : "queue" ](function(){// 执行each或queue方法   
    88.             var opt = jQuery.extend({}, optall), p,   
    89.                 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),// 是元素节点且是隐藏的   
    90.                 self = this;// 当前的元素   
    91.        
    92.             for ( p in prop ) {   
    93.                 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )// 已经是完成的状态   
    94.                     return opt.complete.call(this);// 调用complate函数,在用户的callback加上队列的处理   
    95.   
    96.                 if ( ( p == "height" || p == "width" ) && this.style ) {// style中高度,宽度   
    97.                     opt.display = jQuery.css(this"display");// 保存当前元素的display   
    98.                     opt.overflow = this.style.overflow;// 保证没有暗中进行的   
    99.                 }   
    100.             }   
    101.             if ( opt.overflow != null )// 超出部分不见   
    102.                 this.style.overflow = "hidden";   
    103.   
    104.             opt.curAnim = jQuery.extend({}, prop);   
    105.       
    106.             jQuery.each( prop, function(name, val){// 对当前元素的给定的属性进行变化的操作   
    107.                 var e = new jQuery.fx( self, opt, name );   
    108.   
    109.                 if ( /toggle|show|hide/.test(val) )// 传参的属性可以用toggle,show,hide,其它   
    110.                 // 调用当前e.show,e.hide,e.val的方法,jQuery.fx.prototype   
    111.                     e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );                     
    112.                 else {// 支持"+=" 或 "-=" 来让元素做相对运动。   
    113.                     var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),   
    114.                         start = e.cur(true) || 0;// 当前的大小或0   
    115.   
    116.                     if ( parts ) {   
    117.                         var end = parseFloat(parts[2]),// 值   
    118.                             unit = parts[3] || "px";// 单位   
    119.                            
    120.                         if ( unit != "px" ) {// 计算开始的值=(end/cur)*start   
    121.                             self.style[ name ] = (end || 1) + unit;   
    122.                             start = ((end || 1) / e.cur(true)) * start;   
    123.                             self.style[ name ] = start + unit;   
    124.                         }   
    125.   
    126.                         if ( parts[1] )// +=/-=,做相对运行   
    127.                             end = ((parts[1] == "-=" ? -1 : 1) * end) + start;   
    128.   
    129.                         e.custom( start, end, unit );// 动画   
    130.                     } else  
    131.                         e.custom( start, val, "" );// 动画   
    132.                 }   
    133.             });   
    134.             // For JS strict compliance   
    135.             return true;   
    136.         });   
    137.     },   
    138.   
    139.     // 实现队列操作,为jQuery对象中的每个元素都加type的属性,值为fn.   
    140.     queue: function(type, fn){   
    141.         // 可能看出支持一个fn的参数的形式,支持fn的array集形式   
    142.         if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {   
    143.             fn = type;   
    144.             type = "fx";   
    145.         }   
    146.         // type不存在,空字符等,无参数,type:string,fn不存在。肯定不是函数,也不是数组   
    147.         if ( !type || (typeof type == "string" && !fn) )   
    148.             return queue( this[0], type );   
    149.   
    150.         return this.each(function(){   
    151.             if ( fn.constructor == Array )// 数组的形式   
    152.                 queue(this, type, fn);// 存储在元素的type属性中   
    153.             else {   
    154.                 queue(this, type).push( fn );// 加上一个   
    155.   
    156.                 if ( queue(this, type).length == 1 )   
    157.                     fn.call(this);   
    158.             }   
    159.         });   
    160.     },   
    161.   
    162.     stop: function(clearQueue, gotoEnd){   
    163.         var timers = jQuery.timers;   
    164.   
    165.         if (clearQueue)   
    166.             this.queue([]);// 清除   
    167.   
    168.         this.each(function(){   
    169.             // go in reverse order so anything added to the queue during the   
    170.             // loop is ignored   
    171.             for ( var i = timers.length - 1; i >= 0; i-- )   
    172.                 if ( timers[i].elem == this ) {   
    173.                     if (gotoEnd)   
    174.                         // force the next step to be the last   
    175.                         timers[i](true);   
    176.                     timers.splice(i, 1);   
    177.                 }   
    178.         });   
    179.   
    180.         // start the next in the queue if the last step wasn't forced   
    181.         if (!gotoEnd)   
    182.             this.dequeue();   
    183.   
    184.         return this;   
    185.     }   
    186.   
    187. });   
    188.   
    189. // Generate shortcuts for custom animations   
    190. jQuery.each({   
    191.     slideDown: { height:"show" },   
    192.     slideUp: { height: "hide" },   
    193.     slideToggle: { height: "toggle" },   
    194.     fadeIn: { opacity: "show" },   
    195.     fadeOut: { opacity: "hide" }   
    196. }, function( name, props ){   
    197.     jQuery.fn[ name ] = function( speed, callback ){   
    198.         return this.animate( props, speed, callback );   
    199.     };   
    200. });   
    201.   
    202. // 为元素加上type的array的属性,或返回取到elem上type的值   
    203. var queue = function( elem, type, array ) {   
    204.     if ( elem ){   
    205.         type = type || "fx";   
    206.         var q = jQuery.data( elem, type + "queue" );   
    207.         if ( !q || array )   
    208.             q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );   
    209.     }   
    210.     return q;   
    211. };   
    212. // 出列,根据type   
    213. jQuery.fn.dequeue = function(type){   
    214.     type = type || "fx";   
    215.     return this.each(function(){   
    216.         var q = queue(this, type);// 得取type的的值   
    217.         q.shift();// 移出一个   
    218.         if ( q.length )   
    219.             q[0].call( this );   
    220.     });   
    221. };   
    222.   
    223. jQuery.extend({   
    224.      // 主要用于辅助性的工作   
    225.     speed: function(speed, easing, fn) {   
    226.         var opt = speed && speed.constructor == Object ? speed : {// 采用紧凑型方式   
    227.             complete: fn || !fn && easing ||   
    228.                 jQuery.isFunction( speed ) && speed,// coplete是至多三个参数的最后一个,当然是Fn.   
    229.             duration: speed,// 持继的时间   
    230.             easing: fn && easing || easing && easing.constructor != Function && easing// 不是Fn   
    231.         };   
    232.   
    233.         opt.duration = (opt.duration && (opt.duration.constructor == Number ?   
    234.             opt.duration :  jQuery.fx.speeds[opt.duration])) // 存在,不是数值,转找   
    235.             || jQuery.fx.speeds._default;// 默认的   
    236.   
    237.         // Queueing   
    238.         opt.old = opt.complete;   
    239.         opt.complete = function(){// 排队的处理   
    240.             if ( opt.queue !== false )   
    241.                 jQuery(this).dequeue();   
    242.             if ( jQuery.isFunction( opt.old ) )   
    243.                 opt.old.call( this );   
    244.         };   
    245.   
    246.         return opt;   
    247.     },   
    248.   
    249.     // 擦除效果   
    250.     easing: {   
    251.         linear: function( p, n, firstNum, diff ) {   
    252.             return firstNum + diff * p;   
    253.         },   
    254.         swing: function( p, n, firstNum, diff ) {   
    255.             return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;   
    256.         }   
    257.     },   
    258.   
    259.     timers: [],// jQuery.timers   
    260.     timerId: null,   
    261.        
    262.     // 根据参数构成一个对象   
    263.     fx: function( elem, options, prop ){   
    264.         this.options = options;   
    265.         this.elem = elem;   
    266.         this.prop = prop;   
    267.   
    268.         if ( !options.orig )   
    269.             options.orig = {};   
    270.     }   
    271.   
    272. });   
    273.   
    274. jQuery.fx.prototype = {   
    275.   
    276.     // 为元素设值,更新显示   
    277.     update: function(){   
    278.         if ( this.options.step )   
    279.             this.options.step.call( this.elem, this.now, this );   
    280.   
    281.         (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );// 为元素的设值,fx.prop   
    282.   
    283.         // 对于高度和宽度,采用display=block的形式。   
    284.         if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )   
    285.             this.elem.style.display = "block";   
    286.     },   
    287.   
    288.     // 当前元素当前属性的值   
    289.     cur: function(force){   
    290.         if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )   
    291.             return this.elem[ this.prop ];   
    292.   
    293.         var r = parseFloat(jQuery.css(this.elem, this.prop, force));   
    294.         return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;   
    295.     },   
    296.   
    297.     // 开动一个动画   
    298.     custom: function(from, to, unit){   
    299.         this.startTime = now();   
    300.         this.start = from;   
    301.         this.end = to;   
    302.         this.unit = unit || this.unit || "px";   
    303.         this.now = this.start;   
    304.         this.pos = this.state = 0;   
    305.         this.update();   
    306.   
    307.         var self = this;   
    308.         function t(gotoEnd){   
    309.             return self.step(gotoEnd);// 调用step(gotoEnd)//本对象的   
    310.         }   
    311.         t.elem = this.elem;   
    312.         jQuery.timers.push(t);   
    313.             
    314.         // 第一次,或上一次已经把jQuery.timers全部执行完了。   
    315.         if ( jQuery.timerId == null ) {   
    316.             jQuery.timerId = setInterval(function(){   
    317.                 var timers = jQuery.timers;   
    318.                 for ( var i = 0; i < timers.length; i++ )// 执行timers中所有   
    319.                     if ( !timers[i]() )// 执行了一次,就从timers中除去   
    320.                         timers.splice(i--, 1);   
    321.   
    322.                 if ( !timers.length ) {// length==0,取消Interval   
    323.                     clearInterval( jQuery.timerId );   
    324.                     jQuery.timerId = null;   
    325.                 }   
    326.             }, 13);   
    327.         }   
    328.     },   
    329.   
    330.     // Simple 'show' function   
    331.     show: function(){   
    332.         // 保存当前的,以被修改之后能得到初始的值   
    333.         this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );   
    334.         this.options.show = true;   
    335.            
    336.         this.custom(0this.cur());   
    337.   
    338.         // Make sure that we start at a small width/height to avoid any   
    339.         // flash of content   
    340.         if ( this.prop == "width" || this.prop == "height" )   
    341.             this.elem.style[this.prop] = "1px";   
    342.   
    343.         // 开始显示元素   
    344.         jQuery(this.elem).show();   
    345.     },   
    346.   
    347.     // 隐藏   
    348.     hide: function(){   
    349.         // 保存当前的,以被修改之后能得到初始的值   
    350.         this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );   
    351.         this.options.hide = true;   
    352.            
    353.         this.custom(this.cur(), 0);   
    354.     },   
    355.   
    356.     // 动画的每一个步骤   
    357.     step: function(gotoEnd){   
    358.         var t = now();   
    359.          // 结束或当前时间大于startTime+duration   
    360.         if ( gotoEnd || t > this.options.duration + this.startTime ) {   
    361.             this.now = this.end;   
    362.             this.pos = this.state = 1;   
    363.             this.update();   
    364.   
    365.             this.options.curAnim[ this.prop ] = true;   
    366.   
    367.             var done = true;   
    368.             for ( var i in this.options.curAnim )   
    369.                 if ( this.options.curAnim[i] !== true )   
    370.                     done = false;   
    371.   
    372.             if ( done ) {// 重置所有的设定   
    373.                 if ( this.options.display != null ) {// Reset the overflow   
    374.                     this.elem.style.overflow = this.options.overflow;   
    375.                     // Reset the display   
    376.                     this.elem.style.display = this.options.display;   
    377.                     if ( jQuery.css(this.elem, "display") == "none" )   
    378.                         this.elem.style.display = "block";   
    379.                 }   
    380.   
    381.                 // Hide the element if the "hide" operation was done   
    382.                 if ( this.options.hide )   
    383.                     this.elem.style.display = "none";   
    384.   
    385.                 // Reset the properties, if the item has been hidden or shown   
    386.                 if ( this.options.hide || this.options.show )   
    387.                     for ( var p in this.options.curAnim )   
    388.                         jQuery.attr(this.elem.style, p, this.options.orig[p]);   
    389.             }   
    390.   
    391.             if ( done )// 运行complete的回调函数   
    392.                 this.options.complete.call( this.elem );   
    393.   
    394.             return false;   
    395.         } else {   
    396.             var n = t - this.startTime;   
    397.             this.state = n / this.options.duration;   
    398.   
    399.             // Perform the easing function, defaults to swing   
    400.             this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 01this.options.duration);   
    401.             this.now = this.start + ((this.end - this.start) * this.pos);   
    402.   
    403.             // Perform the next step of the animation   
    404.             this.update();   
    405.         }   
    406.   
    407.         return true;   
    408.     }   
    409.   
    410. };   
    411.   
    412. jQuery.extend( jQuery.fx, {   
    413.     // 动画的速度   
    414.     speeds:{   
    415.         slow: 600,   
    416.         fast: 200,   
    417.         // Default speed   
    418.         _default: 400  
    419.     },   
    420.        
    421.     // 为元素设值   
    422.     step: {   
    423.         opacity: function(fx){// 为元素CSS设opacity为fx   
    424.             jQuery.attr(fx.elem.style, "opacity", fx.now);   
    425.         },   
    426.   
    427.         _default: function(fx){   
    428.             if( fx.prop in fx.elem ) // 对于元素   
    429.                 fx.elem[ fx.prop ] = fx.now;   
    430.             else if( fx.elem.style )// 对于style   
    431.                 fx.elem.style[ fx.prop ] = fx.now + fx.unit;   
    432.         }   
    433.     }   
    434. });  
  • 相关阅读:
    正则表达式简介
    PHP中简单的页面缓冲技术
    PHP 程序加速探索
    PHP中通过Web执行C/C++应用程序
    PHP实现聊天室的主动更新与被动更新
    php中Cookie及其使用
    Linux 下 PHP 连接 MS SQLServer 的办法
    网站加速 PHP 缓冲的免费实现方法
    Spark Streaming中的基本操作函数实例
    Scala中的s函数
  • 原文地址:https://www.cnblogs.com/rooney/p/1346129.html
Copyright © 2020-2023  润新知