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

Posted

技术标签:

【中文标题】在动画期间更改 jQuery 的动画持续时间【英文标题】:Change jQuery's animation duration during animating 【发布时间】:2013-01-18 08:44:57 【问题描述】:

是否可以在两个不同的值之间更改当前运行的 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 是的,谢谢!我注意到了……我现在处于核心状态,试着弄清楚如何解决这个问题! 【参考方案1】:

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

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

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

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

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 有easing 选项,但我不确定它是如何工作的,以及是否需要在开始动画之前知道动画速度。 这实际上可以很好地工作,只要 animationCss 带有绝对值(例如,没有 +=50)并且取决于你希望它如何表现得像@Matt 在他的回答中提到的那样。你可以让它看起来很漂亮,将它包装在一个插件中,这应该相对容易做到。 顺便说一下,Matt 代码的一个分支是相对于完成百分比而不是绝对持续时间(基本上是替代行为):fiddle.jshell.net/4mFn4【参考方案2】:

我可能有点迟到了,但由于我在尝试做同样的事情时最终来到这里,其他人也可能。

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

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

【讨论】:

以上是关于在动画期间更改 jQuery 的动画持续时间的主要内容,如果未能解决你的问题,请参考以下文章

jQuery - 动画完成持续时间

无法更改取消选择动画的动画持续时间

防止固定位置元素在 jQuery 动画期间闪烁

jQuery中短距离和长持续时间的微妙字体大小动画

如何在更改其边界的动画期间强制重绘 CALayer

在动画期间更改 SKSpriteNode 的锚点?