jQuery Animation:在动画中期更改动画参数

时间:2012-11-27 18:51:46

标签: jquery animation

假设您有一个很长的动画,您正在更改width

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

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

如何在正在运行的动画中将targetWidth更改为其他值?

4 个答案:

答案 0 :(得分:4)

一种选择是使用jQuery step函数(API)中提到的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函数的start参数的endfx属性来控制动画。这样可以使动画变得平滑,但这并不是一种非常整洁的方式。

示例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;
                }
              }
    });
}); 

答案 1 :(得分:2)

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

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

试试这个

<强> HTML

​<div class="a">

​</div>

​<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);
    }
});​

<强> Check Fiddle

答案 2 :(得分: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 );
}

结果我认为你必须使用已更改的变量停止和重新排队动画,因为你几乎没有希望访问闭包中的任何变量(请有人纠正我)

答案 3 :(得分:0)

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

http://jsfiddle.net/Q3ZcQ/

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

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

CSS     #block {width:100px;身高:100px;背景:红色; }

HTML

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

JQUERY

$('#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" />​