2015-03-08 38 views
1

我写了一个自定义动画函数。它通常工作得很好,但是当我用不同的endCallbacks快速连续呼叫animate();时,有时候回调会非常糟糕,导致在错误的时间进行错误的操作。如果多次调用同一函数的前一个实例,该如何停止?

问题是函数实例化多次并执行直到达到endValue。 currentValue被改变得非常快,以至于我只能看到我的html页面动画中的最后一个值。这隐藏了这种不需要的行为。

我第二次拨打animate();时需要的是结束animate();的第一个实例,并用新值和新回调触发一个新实例。同时我也想停止setTimeout()函数,以确保没有错误的回调被触发。

window.onload = function(){ 
    document.addEventListener('click', // some button 
     function(){ 
      animate(1, 10); 
     }, false 
    ); 
} 

function animate(startValue, endValue, callback, endCallback) { 
    var startValue = startValue, 
     currentValue = startValue, 
     endValue = endValue, 
     callback = callback, 
     timeout = null; 

    loopAnimation(); 
    function loopAnimation(){ 
     if (currentValue != endValue){ 
      timeout = setTimeout(function(){ 
       currentValue++; 

       // Callback executes some page manipulation code 
       if (typeof callback !== "undefined") callback(currentValue); 
       console.log(currentValue); 
       loopAnimation(); 
      },500) 
     } else { 
      console.log("This callback triggers some specific changes in my page"); 
      if (typeof endCallback !== "undefined") endCallback(); 
     } 
    } 
} 

而是在控制台中看到的: 1,2,3, - 1,4,2,5 ...... 6,9,7,10,8,9,10

我'd喜欢看: 1,2,3, - 1,2 ... 7,8,9,10

但请记住,由于我在脚本中使用animate()的方式,我可以绝对不要了解输入变量的名称或范围。这使我无法自己解决它。

+1

你不能阻止一个功能从另一个执行。假设您正在使用jquery进行动画,您可以调用一个'.stop'方法来停止在该元素上运行的所有动画。 http://api.jquery.com/stop/ – lwalden 2015-03-08 21:35:58

回答

1

虽然它不是您要求的实现,但我不知道Underscore的节流或去抖动能否满足需求?

debounce将确保您的函数每秒被调用不超过X次 - 每调用一次它仍会执行一次,但随后的调用将被延迟以满足您的速率限制。所以,如果你连续快速地调用动画两次,去抖动可以延迟第二次执行,直到第一次或你之后的100ms。

throttle基本上会忽略速率限制期间发生的呼叫。所以如果你在100ms内调用你的动画10次,你可以把它扔掉,除了第一次。 (实际上,它将在等待期结束时完成第一个,另外一个)。

您不需要使用所有的下划线来获得这些方法;我已经看到人们经常复制和粘贴下划线的反弹和/或油门功能。如果你是谷歌,你可以找到一些独立的油门或反弹实施。

油门和去抖动通常用于你的情况,动画。

对于你的原始规范,实际上“结束animate()的第一个实例” - 在JavaScript中没有很好的可靠方法来做到这一点。没有真正的通用方法来“取消”已经执行的功能。如果你能使它反弹或节流,我认为它会减少挫折感。

+0

我需要能够随时更改动画对象的状态,因此防止双击它不是我的目的的真正选择。干杯! – 2015-03-09 08:30:53

0

你需要的是存储你使用的最后一个超时ID。因此,下次启动新动画时,请使用此超时ID和clearTimeout清除正在进行的动画。
我发现很方便在函数本身上存储间隔。

在这里看到的jsbin: http://jsbin.com/nadawezete/1/edit?js,console,output

window.onload = function(){ 
    document.addEventListener('click', // some button 
     function(){ 
      animate(1, 10); 
     }, false 
    ); 
}; 

function animate(startValue, endValue, callback, endCallback) { 
    var currentValue = startValue; 
    if (animate.timeout) clearTimeout(animate.timeout); 
    loopAnimation(); 
    function loopAnimation(){ 
     if (currentValue != endValue){ 
      animate.timeout = setTimeout(function(){ 
       console.log(currentValue); 
       currentValue++;  
       // Callback executes some page manipulation code 
       if (callback) callback(currentValue); 
       loopAnimation(); 
      },500); 
     } else { 
      console.log("This callback triggers some specific changes in my page"); 
      if (endCallback) endCallback(); 
     } 
    } 
} 
+0

这与我所寻找的非常接近。对于我的具体用例,它工作得很好,我可以通过创建一个拥有多个setTimeout()的对象来进一步调整这个解决方案。用于多个动画变量的ID。这将有助于动画化不同的对象,而无需重新设置错误对象的动画。非常感谢你! – 2015-03-09 08:35:14

+0

不客气!所以你似乎可以接受这个答案。请注意,如果您执行“很多”(20+以上)的动画,setTimeout开销可能会因您的问题而变得太大。您必须恢复逻辑,并在setInterval或requestAnimationFrame上挂接单个处理程序,以驱动所有动画逻辑。 – GameAlchemist 2015-03-09 08:57:10

+0

在我目前的项目中,我使用requestAnimationFrame();对于多个画布和页面操作,事实上,它确实通过明显的措施提高了整体性能。为了使不需要的行为容易被注意,我简化了示例代码。我将替换clearTimeout();与cancelAnimationFrame();非常感谢您的反馈! – 2015-03-09 09:39:58

相关问题