使用requestAnimationFrame时出现的错误行为

3

我写了一个有用的库来绘制和动画化SVG路径:segment。你可以在github上查看

一段时间以前,我(接受了一个Pull Request)用requestAnimationFrame替换了setTimeout调用,以加快现代浏览器中的动画速度,还使用了Paul Irish提供的polyfill

现在,当我尝试在多个paths之间设置非常低的延迟时,我正在尝试使用requestAnimationFrame调用的错误行为。

我准备了两个演示文稿,展示了setTimeout(正常工作)和requestAnimationFrame(错误行为)的行为。请检查它:

requestAnimationFrame演示中,我对我的库进行了一些修改,以便在控制台打印出一些有用的信息,您可以在其中看到错误行为:

(function calc(){
    // Checking if it's the first element, the buggy behavior happens in the firsts elements
    if(that.class === 'first'){
        console.log('calc');
    }

    // Some code here that can break the recursive loop and stop execution of calc function

    if(that.class === 'first'){
        console.log('calc call');
    }
    that.timer = window.requestAnimationFrame(calc);

    // More code here
})();

根据先前的代码,每次出现“calc call”消息后都应该出现一个“calc”消息。但至少在Firefox和Chrome中,我看不到这种情况。这是大多数时候的控制台输出:
calc
calc call
calc
calc call

我真的不知道发生了什么事情,所以任何帮助都是受欢迎的 :)


我有点困惑。你说“每次‘calc call’之后都应该得到一个‘calc’”。但是你的代码做了相反的操作。虽然输出看起来是正确的。 - Paul LeBeau
@PaulLeBeau 对不起,你可能没明白,我再试着换个方式解释一下。在控制台中,首先必须接收到“calc”,到这里一切都很完美。稍后,应该会出现一个“calc call”的消息,随后被调用回calc函数时,另一个“call”消息也必须出现(在calc函数的第一句话)。最后的控制台输出不能是“call calc”,而必须是“calc”,因为唯一停止循环的方法是放在写有 // Some code here 的地方。希望现在清楚了,并且抱歉回答的延迟。 - lmgonzalves
如果你需要退出循环函数,只需调用 return。如果没有再次调用 requestAnimationFrame(),那么循环将在那里停止。 - Paul LeBeau
@PaulLeBeau 我实际上是通过一个 if 条件退出了循环,这不是问题。问题在于我调用了 window.requestAnimationFrame(calc);,而在第二次调用中它没有运行 calc 函数,因为 'calc' 消息没有显示。 - lmgonzalves
无法在FF44.0.2中重现。 - Serge Seredenko
@SergeSeredenko 刚刚升级了我的 FF 至该版本,但问题仍然存在。有时候运行正常,但大部分时间都有 bug。 - lmgonzalves
1个回答

2
这里出现错误的原因是将timeoutIDrequestAnimationFrame的返回值都保存在同一个变量中。将它们保存在不同的变量中即可解决问题。
这是一个CodePen示例: http://codepen.io/anon/pen/KzPboY?editors=0010

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