requestAnimationFrame未取消

时间:2013-08-13 19:48:46

标签: javascript animation html5-canvas

我正在开发一款使用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);
};

问题是我收到了消息cancel the game now,然而游戏继续运行,因为animationFrame在某种程度上没有被取消。我尝试了webkitCancelAnimationFramecancelAnimationFramewebkitCancelRequestAnimationFrame以及在浏览器中请求动画帧的所有版本:requestAnimationFramewebkitRequestAnimationFrame。这些组合都不起作用。

奇怪的是,如果我在webkit检查器控制台中运行window.webkitCancelRequestAnimationFrame(window.animationID),游戏将按预期停止。我将此代码window.webkitCancelRequestAnimationFrame(window.animationID); console.log('button test')添加到DOM按钮的onclick属性中,当我单击它时游戏停止,但是当我执行JS theDOMButton.click()时没有任何反应,但我确实得到了消息'按钮测试”。

这是我的用户代理:

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36

这是一个jsfiddle:

http://jsfiddle.net/mJPMt/

更改为此后:http://pastebin.com/ewDXBT9C它可以正常工作,但我认为它很奇怪,因为请求动画应该停止而不需要在每个循环中检查变量

2 个答案:

答案 0 :(得分:4)

您需要在设置id

后调用更新
(function tick () {
    id = webkitRequestAnimationFrame(tick);
    update();
}());

否则它会停止旧的,但新的仍在设置中。

<强> FIDDLE

要解决Vincent Piel带来的问题,您可以像update一样promise。这是使用此方法的fiddle。它与他的答案中的类似,除了你不需要有范围的布尔值。

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

答案 1 :(得分:0)

你看到的行为是完全正常的:发生的事情是你在update()方法中完成了取消。
所以你实际取消的是之前的 rAF,并且无论发生在更新中的什么,你都会启动另一个rAF。

(function tick() {

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

}());

当您在控制台中执行此操作时,您将取消 next rAF,因此游戏将停止。

所以你需要使用布尔来让循环停止,甚至不保存动画ID。

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

var animCancelled = false;
(function tick() {

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

}());