动画期间更改jQuery的动画持续时间

7

是否可以在两个不同的值之间更改当前运行的jQuery动画的duration

我尝试通过直接赋值来更改duration,但没有成功:

var timing = { duration: 4000 };
$(document).click(function (e) {
  timing.duration = 1000;
});

$('#foo').animate({top:200, left:200}, timing);

即使在step方法中更改fx.options.duration也不会影响正在运行的动画:

var state = false,
$(document).click(function (e) {
  state = true;
});

$('#foo').animate({top:200, left:200}, {
  duration: 4000,
  step: function(now, fx){
    if(state) fx.options.duration = 1000;
    console.log(fx.options.duration); // 1000
  }
});

这里有一个可以玩耍的fiddle

有什么想法如何做到这一点?


如果你从jQuery 2.0切换到jQuery >= 1.7.2,它(在某种程度上)可以工作。我猜这与jQuery团队对动画相关函数所做的最近更改有关。 - Mahn
@Mahn 好的,谢谢!我已经注意到了...我现在在核心部分,试图弄清楚如何解决这个问题! - yckart
2个回答

10

持续时间是以值传递的,而不是按引用传递。所以animate不会存储duration的引用。即使您更新了通过引用传递的选项对象,jQuery也会在内部使用options.duration,这意味着它将被按值传递。

作为一个快速修复,您可以停止动画并使用新的持续时间重新启动它 - 调整已经完成的部分的动画。

您需要考虑您希望它如何行动,例如当您将4秒动画加速到2秒动画后3秒时。在下面的代码中,动画将是立即的。认真考虑,这可能不是您想要的,因为您可能真正关心的是速度而不是持续时间。

以下代码是一个粗略的草图,我不确定它是否准确,是否能够处理减少动画值或如何处理多个动画值。您也只能更改持续时间一次。

var state = false,
    duration = 8000;

$(document).click(function (e) {
    state = true;
    duration = 1000;
});
var animationCss = {top:200, left:200};
$('#foo').animate(animationCss, {
    duration: duration,
    step: function(now, fx){
        if(state) {
             $("#foo").stop();
             var percentageDone = (fx.now - fx.start) / (fx.end - fx.start) 
             var durationDone = fx.options.duration * percentageDone;
             var newDuration = duration - durationDone;
            if (newDuration < 0)
            {
                 newDuration = 0;   
            }
            $("#foo").animate(animationCss, { duration: newDuration})

        }
    }
});

http://fiddle.jshell.net/5cdwc/3/


是的,谢谢你的想法和解释!这个想法很棒,但我认为,在某些地方肯定有更好的解决方法! - yckart
@yckart 有一个 easing 选项,但我不确定它是如何工作的,以及在开始动画之前是否需要知道动画速度。 - Matt Zeunert
只要animationCss带有绝对值(例如没有+=50),并且根据您想让它像@Matt在他的答案中提到的那样行为,这实际上可以很好地工作。您可以将其包装在插件中,使其看起来漂亮,这应该相对容易做到。 - Mahn
这是Matt代码的一个分支,与绝对持续时间相比,它是关于完成百分比的(基本上是替代行为):http://fiddle.jshell.net/4mFn4/ - Mahn

0

我可能有点晚回复,但既然我在尝试做同样的事情时来到了这里,其他人也可能会。

start() 回调中,jQuery将动画对象作为参数传递,因此您只需在某个地方保留引用,然后就可以在 step() 回调中更改它。

类似于:

var animEnd = false; //this will be updated somewhere else 
var animObj;
$().animate({
        width: '100%'
    },
    {   
        start: function(animation){
            animObj = animation;
        },
        step: function(now, tween){
            if(!animEnd)
                //jquery set an interval of 13 but let's be safe
                animObj.duration += 30;

            //you can change the value of tween.pos aswell
        }
    }
);

现在棘手的部分是,在调用step()回调之前,jQuery决定停止或继续动画。因此,持续时间设置为下一个刻度,如果没有设置足够大,则可能会停止动画。
jQuery使用间隔为13的setInterval(),理论上应该每13毫秒调用一次step(),但由于没有任何保证,我认为持续时间应该至少增加30毫秒。
个人而言,我甚至会选择至少100毫秒。最好有一个运行时间略长(100毫秒几乎不可察觉)的动画,而不是让它过早停止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接