8

假设你有一个很长的动画,你正在改变width

var myTargetWidth = 500;
$(el).animate( { "width" : myTargetWidth }, 5000 );

动画是异步的,因此您的代码将继续。. . 几秒钟后,您决定将目标更改width300. . . 此时动画仍在运行。. .

如何在运行动画中将 targetWidth 更改为不同的值?

4

4 回答 4

5

一种选择是使用jQuery函数 ( APIstep )中提到的函数在动画运行时检查条件。animate

示例 JSFiddle:http: //jsfiddle.net/GweLA/13/

JS

var myTargetWidth = 500;

$(document).ready(function(){
    $('.sample').animate( { "width" : myTargetWidth },{
        duration : 5000,      
        step: function(now, fx) {
            if($(this).width() > 200){
              myTargetWidth = 300;
              $(this).stop().animate({ "width" : myTargetWidth },1000);
            }
        }
    });
});

CSS

.sample{
    width:20px;
    height:100px;
    background-color:#cccccc;    
}

HTML

<div class="sample">
   width is supposed to be animated till 500 but it stops at 300
</div>

解决方案2:

经过一番研究,我发现我们可以修改传递给 step 函数的参数的startend属性来控制动画。fx这种平滑动画,但不是一种非常整洁的方式。

示例 JSFiddle:http: //jsfiddle.net/GweLA/57/

JS

var myTargetWidth = 500;
var isExecuted = false;
$(document).ready(function(){
    $('.sample').animate( { "width" : myTargetWidth },{
        duration : 5000,
        queue : false,
        step: function(now, fx) {
                 //So that fx.start and fx.end is set only once                
                if($(this).width() > 200 && $(this).width() < 203){
                    if(!isExecuted){
                        fx.start = now-65;
                        fx.end = 300;
                    }
                    isExecuted = true;
                }
              }
    });
}); 
于 2012-11-27T19:23:27.313 回答
2

您可以使用.stop()的组合- 停止动画。

:animated选择器 - 检查当前元素是否正在动画..

试试这个

HTML

​&lt;div class="a">

​&lt;/div>

​&lt;button id="check">Check Animation </button>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

Javascript

var myTargetWidth = 300;
var $el = $('.a')
$el.animate({
    "width": myTargetWidth
}, 5000);

$('#check').on('click', function() {
    var newHeight = 300;
    if ($('.a:animated')) {
        $el.stop().animate({
            "height": newHeight
        }, 5000);
    }
});​

检查小提琴

于 2012-11-27T19:01:27.487 回答
0

查看 jquery github 中的 effects.js,你会在赋值后更改变量时遇到问题

来源:https ://github.com/jquery/jquery/blob/master/src/effects.js

注意:注意 .animate 中的分配和对象创建到动画(工作马)

animate: function( prop, speed, easing, callback ) {
    var empty = jQuery.isEmptyObject( prop ),
    optall = jQuery.speed( speed, easing, callback ),
    doAnimation = function() {
        // Operate on a copy of prop so per-property easing won't be lost
        var anim = Animation( this, jQuery.extend( {}, prop ), optall );

        // Empty animations resolve immediately
        if ( empty ) {
           anim.stop( true );
        }
    };

return empty || optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
}

//在effects.js中动画

function Animation( elem, properties, options ) {
    var result,
        index = 0,
        length = animationPrefilters.length,
        deferred = jQuery.Deferred().always( function() {
            // don't match elem in the :animated selector
            delete tick.elem;
        }),
        tick = function() {
            var currentTime = fxNow || createFxNow(),
                remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
                // 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 ( percent < 1 && length ) {
                return remaining;
            } else {
                deferred.resolveWith( elem, [ animation ] );
                return false;
            }
        },
        animation = deferred.promise({
            elem: elem,
            props: jQuery.extend( {}, properties ),
            opts: jQuery.extend( true, { specialEasing: {} }, options ),
            originalProperties: properties,
            originalOptions: options,
            startTime: fxNow || createFxNow(),
            duration: options.duration,
            tweens: [],
            createTween: function( prop, end ) {
                var tween = jQuery.Tween( elem, animation.opts, prop, end,
                        animation.opts.specialEasing[ prop ] || animation.opts.easing );
                animation.tweens.push( tween );
                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;

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

                // resolve when we played the last frame
                // otherwise, reject
                if ( gotoEnd ) {
                    deferred.resolveWith( elem, [ animation, gotoEnd ] );
                } else {
                    deferred.rejectWith( elem, [ animation, gotoEnd ] );
                }
                return this;
            }
        }),
        props = animation.props;

    propFilter( props, animation.opts.specialEasing );

    for ( ; index < length ; index++ ) {
        result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
        if ( result ) {
            return result;
        }
    }

    createTweens( animation, props );

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

    jQuery.fx.timer(
        jQuery.extend( tick, {
            anim: animation,
            queue: animation.opts.queue,
            elem: elem
        })
    );

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

结果,我认为您将不得不 .stop 并使用更改的变量重新排列动画,因为您几乎没有希望访问闭包中的任何变量(请有人纠正我)

于 2012-11-27T19:07:50.597 回答
0

我在这里添加了一个示例:

http://jsfiddle.net/Q3ZcQ/

尝试单击动画中的“单击此处”元素...

我使用clearQueue()andstop()函数。

CSS #block { 宽度:100px; 高度:100px;背景:红色;}​</p>

HTML

<p>
  <a id="clickme">Click here</a>
</p>

查询

$('#clickme').not('.again').on('mouseup',function() {
  $(this).addClass('again');
  $('#block').animate({
    width: '400'
  }, 5000, function() {
    // Animation complete.
  });
});

$('.again').live('mousedown', function() {
    $(this).removeClass('again');
 $('#block').clearQueue().animate({
    width: '200',
  }, 500, function() {
     $('#block').stop(true, false);
  });
});​
<div id="block" />​
于 2012-11-27T19:16:24.233 回答