如何停止requestAnimationFrame递归/循环?如何停止requestAnimatio

2019-05-14 11:27发布

我使用three.js所用WebGL的渲染,使游戏的时全屏播放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方法,是的,因为预期它的工作。 但是,当我打电话的stopAnimating功能,打破东西! 有没有报告的错误,但...

设置基本上是这样的:

  • 有一个play网页上的连结
  • 一旦用户点击该链接,渲染器的domElement应全屏,并且它
  • startAnimating方法被调用,渲染器渲染开始东东
  • 一旦逃避被点击时,我注册一个fullscreenchange事件并执行stopAnimating方法
  • 页面试图退出全屏模式,确实如此,但整个文件是完全空白

我敢肯定,我的其他代码是OK,那我莫名其妙地停止requestAnimationFrame以错误的方式。 我的解释可能吸走,所以我上传的代码到我的网站,你可以看到它发生在这里: http://banehq.com/Placeholdername/main.html 。

下面是版本,我不尝试调用动画的方法,并fullscreening进出作品: http://banehq.com/Correct/Placeholdername/main.html 。

一旦play点击还是第一次,游戏初始化,它的start方法被执行。 一旦退出全屏模式,游戏的stop正在执行的方法。 每隔一个时间play已被点击,游戏只执行它的start方法,因为没有必要为它重新初始化。

下面是它的外观:

var playLinkHasBeenClicked = function()
{
    if (!started)
    {
        started = true;

        game = new Game(container); //"container" is an empty div
    }

    game.start();
}

而这里的如何startstop方法如下所示:

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

这和工作版本之间的唯一区别是, startAnimatingstopAnimating方法调用 startstop方法被注释掉。

Answer 1:

启动/停止的一种方法是这样的

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("#time"); var requestId; function loop(time) { requestId = undefined; doStuff(time) start(); } function start() { if (!requestId) { requestId = window.requestAnimationFrame(loop); } } function stop() { if (requestId) { window.cancelAnimationFrame(requestId); requestId = undefined; } } function doStuff(time) { timeElem.textContent = (time * 0.001).toFixed(2); } document.querySelector("#start").addEventListener('click', function() { start(); }); document.querySelector("#stop").addEventListener('click', function() { stop(); }); 
 <button id="start">start</button> <button id="stop">stop</button> <div id="time"></div> 



Answer 2:

停车是不调用requestAnimationFrame了,因为简单,并重新启动是再次称呼它吧。 EX)

        var pause = false;
        function loop(){
                //... your stuff;
                if(pause) return;
                window.requestionAnimationFrame(loop);
        }
       loop(); //to start it off
       pause = true; //to stop it
       loop(); //to restart it


Answer 3:

我建议有一个看requestAnimationFrame填充工具 gibhub页。 有大约这是如何实现的讨论。



Answer 4:

所以,做一些更多的测试后,我发现了它,的确,我是提出了一个问题,而不是动画停止(这毕竟是一个简单而又重复的)其他代码。 问题是在动态添加和从页面移除渲染器的一个DOMElement。 我已经停止这样做之后,确实没有理由这样做,并包含一次在初始化发生了什么,一切都开始正常工作。



Answer 5:

我打得四处一的教程2D突围赛 ,他们还使用requestAnimationFrame,我用一个简单的停止它的回报 。 如果省略返回值的return语句结束函数执行。

if(!lives) {
    alert("GAME OVER");
    return;
}

// looping the draw()
requestAnimationFrame(draw);


文章来源: How to stop a requestAnimationFrame recursion/loop?