我正在开发一款使用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
。这些组合都不起作用。
奇怪的是,如果我在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://pastebin.com/ewDXBT9C它可以正常工作,但我认为它很奇怪,因为请求动画应该停止而不需要在每个循环中检查变量
答案 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);
}());