Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/421.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript requestAnimationFrame不为';t取消_Javascript_Animation_Html5 Canvas - Fatal编程技术网

Javascript requestAnimationFrame不为';t取消

Javascript requestAnimationFrame不为';t取消,javascript,animation,html5-canvas,Javascript,Animation,Html5 Canvas,我正在开发一个使用requestAnimationFrame的游戏。这是代码 Game.prototype.startLoop = function (arg) { var parent = this; (function tick() { parent.update(); window.animationID = webkitRequestAnimationFrame(tick); }()); }; Game.prototyp

我正在开发一个使用requestAnimationFrame的游戏。这是代码

Game.prototype.startLoop = function (arg) {

    var parent = this;

    (function tick() {

        parent.update();
        window.animationID = webkitRequestAnimationFrame(tick);

    }());

};

Game.prototype.stopLoop = function () {
    console.log('cancel the game now');
    window.webkitCancelRequestAnimationFrame(window.animationID);
};
问题是,我收到消息,
立即取消游戏
,但是游戏继续运行,因为animationFrame没有被取消。我已经尝试了
webkitCancelAnimationFrame
cancelAnimationFrame
webkitcancerequestanimationframe
,以及在我的浏览器中请求动画帧的所有版本:
requestAnimationFrame
webkitRequestAnimationFrame
。这些组合都不起作用

奇怪的是,如果我在webkit inspector控制台中运行
window.webkitCancelRequestAnimationFrame(window.animationID)
,游戏会按预期停止。我添加了这个代码
window.webkitCancelRequestAnimationFrame(window.animationID);将console.log('button test')
添加到DOM按钮的onclick属性,当我单击它时,游戏停止,但当我执行JS
theDOMButton.click()时,什么都没有发生,但我确实收到消息“button test”

这是我的用户代理:

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
下面是一个JSFIDLE:


更改为此后:它可以工作,但我认为这很奇怪,因为请求动画应该停止,而不需要在每个循环中使用变量进行检查

您看到的行为是完全正常的:所发生的是,您在update()方法中完成了取消操作。
所以你要取消的实际上是以前的皇家空军,你发射了另一架皇家空军,不管更新中发生了什么

(function tick() {

    parent.update(); // here we cancel the last window.animationID
    window.animationID = rAF(tick); // here we go again, we launch another rAF

}());
当你在控制台上做这件事时,你将取消下一个皇家空军,因此游戏停止

因此,您需要使用布尔值使循环停止,甚至不保存动画id

我不知道您希望如何处理这个布尔值(闭包/名称空间/全局变量),但它看起来像:

var animCancelled = false;
(function tick() {

    parent.update(); 
    if (!animCancelled) rAF(tick); 

}());

设置
id

(function tick () {
    id = webkitRequestAnimationFrame(tick);
    update();
}());
否则它会阻止旧的,但新的仍在设置中

为了解决Vincent Piel提出的问题,您可以像承诺一样执行
更新
。下面是一个使用这种方法的例子。它与他的答案中的类似,只是不需要作用域布尔值

function update() {
    var dfd = $.Deferred();
    x += 0.1;
    y += 0.1;

    if (x > 50) {
        dfd.reject();
        return;
    }

    draw();
    dfd.resolve();

    return dfd.promise();
}

(function tick () {
    update().done(function() {
        id = webkitRequestAnimationFrame(tick);
    });
}());

首先,使用填隙片/填充胶。你的代码会破坏所有不是webkit的东西。谢谢,但我使用webkit,所以现在不需要Pollyfill,他们不会对我的问题做任何事情。你能把你的代码简化成一个小测试,可以重新解决问题吗?理想的情况下,把它作为一个小玩意儿发布?很有可能是其他交互导致了该问题。您也可以尝试在请求下一个动画帧之前更改逻辑以检查布尔值。这将是有趣的,看看这是否会改变任何方式的行为
如果(!stopped)webkitRequestAnimationFrame(勾选)
如果更新持续时间过长,则会出现问题:将在前一个更新结束之前调用另一个更新。由于更新时间长,刷新率高(例如120Hz),这可能真的会发生,特别是当邪恶的垃圾收集器暂停更新时。@VincentPiel我更新了我的答案,加入了另一个肯定不会有这个问题的可能解决方案。