Javascript requestAnimationFrame不为';t取消
我正在开发一个使用requestAnimationFrame的游戏。这是代码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
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属性,当我单击它时,游戏停止,但当我执行JStheDOMButton.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我更新了我的答案,加入了另一个肯定不会有这个问题的可能解决方案。