我将 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
方法 - 页面试图退出全屏,确实如此,但整个文档完全是空白
我很确定我的其他代码没问题,而且我以某种错误的方式停止了 requestAnimationFrame
。我的解释可能很糟糕,所以我将代码上传到我的网站,你可以在这里看到:http://banehq.com/Placeholdername/main.html .
这是我不尝试调用动画方法的版本,全屏进出工作: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();
}
下面是 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
方法被注释掉。
最佳答案
启动/停止的一种方式是这样的
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>
关于javascript - 如何停止 requestAnimationFrame 递归/循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10735922/