Javascript 如何停止requestAnimationFrame递归/循环?
我正在使用带有WebGL渲染器的Three.js制作一个游戏,当点击Javascript 如何停止requestAnimationFrame递归/循环?,javascript,html,fullscreen,webgl,three.js,Javascript,Html,Fullscreen,Webgl,Three.js,我正在使用带有WebGL渲染器的Three.js制作一个游戏,当点击play链接时,游戏将全屏显示。对于动画,我使用requestAnimationFrame 我是这样开始的: self.animate = function() { self.camera.lookAt(self.scene.position); self.renderer.render(self.scene, self.camera); if (self.willAnimate) w
play
链接时,游戏将全屏显示。对于动画,我使用requestAnimationFrame
我是这样开始的:
self.animate = function()
{
self.camera.lookAt(self.scene.position);
self.renderer.render(self.scene, self.camera);
if (self.willAnimate)
window.requestAnimationFrame(self.animate, self.renderer.domElement);
}
self.startAnimating = function()
{
self.willAnimate = true;
self.animate();
}
self.stopAnimating = function()
{
self.willAnimate = false;
}
当我需要时,我调用startAnimating
方法,是的,它确实按预期工作。但是,当我调用stop animating
函数时,一切都中断了!但是,没有报告错误
设置基本上如下所示:
self.animate = function()
{
self.camera.lookAt(self.scene.position);
self.renderer.render(self.scene, self.camera);
if (self.willAnimate)
window.requestAnimationFrame(self.animate, self.renderer.domElement);
}
self.startAnimating = function()
{
self.willAnimate = true;
self.animate();
}
self.stopAnimating = function()
{
self.willAnimate = false;
}
- 页面上有一个
链接play
- 一旦用户单击该链接,渲染器的
就会全屏显示,而且它确实会全屏显示domeElement
- 调用
方法,渲染器开始渲染内容startAnimating
- 单击escape后,我注册一个
事件,并执行fullscreenchange
方法stopAnimating
- 页面试图全屏退出,但整个文档完全为空
requestAnimationFrame
。我的解释可能很糟糕,所以我把代码上传到我的网站上,你可以在这里看到它的发生:
以下是我不尝试调用动画方法的版本,全屏输入和输出都有效:
第一次单击play
后,游戏将初始化,并执行start
方法。一旦全屏退出,游戏的stop
方法就会执行。每隔单击play
一次,游戏只执行它的start
方法,因为不需要再次初始化它
下面是它的外观:
var playLinkHasBeenClicked = function()
{
if (!started)
{
started = true;
game = new Game(container); //"container" is an empty div
}
game.start();
}
下面是start
和stop
方法的样子:
self.start = function()
{
self.container.appendChild(game.renderer.domElement); //Add the renderer's domElement to an empty div
THREEx.FullScreen.request(self.container); //Request fullscreen on the div
self.renderer.setSize(screen.width, screen.height); //Adjust screensize
self.startAnimating();
}
self.stop = function()
{
self.container.removeChild(game.renderer.domElement); //Remove the renderer from the div
self.renderer.setSize(0, 0); //I guess this isn't needed, but welp
self.stopAnimating();
}
此版本与工作版本之间的唯一区别是
startAnimating
和stopAnimating
方法调用start
和stop
方法被注释掉。我建议查看gibhub页面。有关于如何实现的讨论。因此,在做了更多的测试之后,我发现,确实是我的其他代码造成了问题,而不是动画停止(毕竟这是一个简单的递归)。问题在于在页面中动态添加和删除渲染器的domeElement。在我停止这样做之后,因为实际上没有理由这样做,并且在初始化发生的地方包括了它,一切都开始正常工作。启动/停止的一种方法是这样的
var requestId;
function loop(time) {
requestId = undefined;
...
// do stuff
...
start();
}
function start() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function stop() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
工作示例:
const timeElem=document.querySelector(“时间”);
var请求id;
函数循环(时间){
requestId=未定义;
多斯塔夫(时间)
start();
}
函数start(){
如果(!requestId){
requestId=window.requestAnimationFrame(循环);
}
}
函数停止(){
if(请求ID){
window.cancelAnimationFrame(请求ID);
requestId=未定义;
}
}
函数doStuff(时间){
timeElem.textContent=(time*0.001).toFixed(2);
}
document.querySelector(“#start”).addEventListener('click',function(){
start();
});
document.querySelector(“#stop”).addEventListener('click',function(){
停止();
});代码>
开始
停止
停止就像不再调用requestAnimationFrame一样简单,重新启动就是再次调用它。
ex)
我玩了一个他们也使用requestAnimationFrame的教程,我用一个简单的例子停止了它。如果省略return的值,return语句将结束函数执行
if(!lives) {
alert("GAME OVER");
return;
}
// looping the draw()
requestAnimationFrame(draw);
这应该是cancelAnimationFrame
而不是cancelRequestAnimationFrame
?改变了,尽管在我的辩护中它最初被称为cancelRequestAnimationFrame
。您可以通过在Chrome中打开控制台并键入webkitCancel
来验证这一点,您将看到webkitCancelRequestAnimationFrame
在Chrome 33中仍然存在,这两个函数的文档可以在MDN上找到:(感谢您提供的精彩信息!)关于我发现的东西,不能从函数内部停止循环:这里是a。仅从外部:-)实际上可以从函数内部取消循环,如下所示:setTimeout(函数(){window.cancelAnimationFrame(requestId);},0)代码>是。这实际上是最简单的方法,但效率不高,因为这样你就必须在每个动画帧内执行检查。我发现cancelAnimationFrame()在繁重的动画循环中执行效率更高。我不明白为什么用户3363398的解决方案比gman的效率低。在gmans解决方案中,在循环中有一个函数调用,然后该函数调用依次执行检查。那不是更重吗?一次检查与函数调用+检查。这将属于@user3363398建议的停止动画帧循环的“不启动下一个循环”方法,另一种方法是使用cancelAnimationFrame()
。