现在的位置: 首页 > 综合 > 正文

jQuery源码分析18: .animate()(待续)

2019年10月29日 ⁄ 综合 ⁄ 共 4468字 ⁄ 字号 评论关闭

jQuery源码分析18: .animate()(待续)

var rfxtypes    = /^(?:toggle|show|hide)$/,

    rfxnum      = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i;

_mark: function( elem, type ) {
    if ( elem ) {
        type = ( type || "fx" ) + "mark";
        jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
    }
},

fx: function( elem, options, prop ) {
    this.options = options;
    this.elem = elem;
    this.prop = prop;
 
    options.orig = options.orig || {};
}

prop: function( elem, name, value ) {
    var ret, 
        hooks, 
        notxml,
        nType = elem.nodeType;
 
    // don't get/set properties on text, comment and attribute nodes
    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
        return;
    }
 
    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
 
    if ( notxml ) {
        // Fix name and attach hooks
        name = jQuery.propFix[ name ] || name;
        hooks = jQuery.propHooks[ name ];
    }
 
    if ( value !== undefined ) {
        if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
            return ret;
        } else {
            return ( elem[ name ] = value );
        }
    } else {
        if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
            return ret;
        } else {
            return elem[ name ];
        }
    }
},

animate: function( prop, speed, easing, callback ) {
    var optall = jQuery.speed( speed, easing, callback );
 
    if ( jQuery.isEmptyObject( prop ) ) {
        return this.each( optall.complete, [ false ] );
    }
 
    // Do not change referenced properties as per-property easing will be lost
    prop = jQuery.extend( {}, prop );
 
    function doAnimation() {
        // XXX 'this' does not always have a nodeName when running the
        // test suite
 
        if ( optall.queue === false ) {
            jQuery._mark( this );
        }
 
        var opt = jQuery.extend( {}, optall ),
            isElement = this.nodeType === 1,
            hidden = isElement && jQuery(this).is(":hidden"),
            name,
            val,
            p,
            e,
            parts,
            start,
            end,
            unit,
            method;
 
        // will store per property easing and be used to determine when an animation is complete
        opt.animatedProperties = {};
 
        for ( p in prop ) {
            // property name normalization
            name = jQuery.camelCase( p );
            if ( p !== name ) {
                prop[ name ] = prop[ p ];
                delete prop[ p ];
            }
 
            val = prop[ name ];
 
            // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
            if ( jQuery.isArray( val ) ) {
                opt.animatedProperties[ name ] = val[ 1 ];
                val = prop[ name ] = val[ 0 ];
            } else {
                opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
            }
 
            if ( val === "hide" && hidden || val === "show" && !hidden ) {
                return opt.complete.call( this );
            }
 
            if ( isElement && ( name === "height" || name === "width" ) ) {
                // Make sure that nothing sneaks out. Record all 3 overflow attributes because IE does not
                // change the overflow attribute when overflowX and overflowY are set to the same value
                opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
 
                // Set display property to inline-block for height/width
                // animations on inline elements that are having width/height animated
                if ( jQuery.css( this, "display" ) === "inline" && jQuery.css( this, "float" ) === "none" ) {
                    // 1).inline-level elements accept inline-block;
                    // 2).block-level elements need to be inline with layout
                    if (!jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline") {
                        this.style.display = "inline-block";
                    } else {
                        this.style.zoom = 1;
                    }
                }
            }
        }
 
        if ( opt.overflow != null ) {
            this.style.overflow = "hidden";
        }
 
        for ( p in prop ) {
            e = new jQuery.fx( this, opt, p );
            val = prop[ p ];
 
            if ( rfxtypes.test( val ) ) {
                // Tracks whether to show or hide based on private data attached to the element
                method = jQuery._data( this, "toggle" + p )||( val === "toggle" ? hidden ? "show" : "hide" : 0 );
                if ( method ) {
                    jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
                    e[ method ]();
                } else {
                    e[ val ]();
                }
            } else {
                parts = rfxnum.exec( val );
                start = e.cur();
 
                if ( parts ) {
                    end = parseFloat( parts[2] );
                    unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
 
                    // We need to compute starting value
                    if ( unit !== "px" ) {
                        jQuery.style( this, p, (end || 1) + unit);
                        start = ( (end || 1) / e.cur() ) * start;
                        jQuery.style( this, p, start + unit);
                    }
 
                    // If a +=/-= token was provided, we're doing a relative animation
                    if ( parts[1] ) {
                        end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
                    }
 
                    e.custom( start, end, unit );
                } else {
                    e.custom( start, val, "" );
                }
            }
        }
 
        // For JS strict compliance
        return true;
    }
 
    return optall.queue === false ?
        this.each( doAnimation ) :
        this.queue( optall.queue, doAnimation );
},

抱歉!评论已关闭.