3

我正在开发一个使用 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 没有被取消。我已经尝试过webkitCancelAnimationFrame, cancelAnimationFrame,webkitCancelRequestAnimationFrame和所有在我的浏览器中请求动画帧的版本:requestAnimationFrame, webkitRequestAnimationFrame. 这些组合都不起作用。

奇怪的是,如果我window.webkitCancelRequestAnimationFrame(window.animationID)在 webkit 检查器控制台中运行,游戏会按预期停止。我将此代码添加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它可以工作,但我认为它很奇怪,因为请求动画应该停止而不需要在每个循环中检查一个变量

4

2 回答 2

4

您需要在设置后调用更新id

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

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

小提琴

要解决 Vincent Piel 提出的问题,您总是可以updatepromise. 这是使用这种方法的小提琴。它与他的回答中的类似,只是您不需要范围布尔值。

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);
    });
}());
于 2013-08-13T21:03:31.640 回答
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

}());

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

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

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

var animCancelled = false;
(function tick() {

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

}());
于 2013-08-13T20:56:32.650 回答