75

playリンクがクリックされたときにフルスクリーンになるゲームを作成するために、WebGL レンダラーで Three.js を使用しています。アニメーションには、 を使用します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間違った方法で停止しています。私の説明はおそらくひどいものだったので、コードを私の Web サイトにアップロードしまし

これは、アニメーション メソッドを呼び出そうとしないバージョンで、フルスクリーンのインとアウトが機能します: 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();
}

これと実際のバージョンの唯一の違いは、startAnimatingandstopAnimatingメソッドが呼び出さstartstopメソッドがコメント アウトされていることです。

4

6 に答える 6

137

開始/停止する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>

于 2012-05-25T05:10:54.237 に答える
22

停止は requestAnimationFrame をもう呼び出さないのと同じくらい簡単で、再起動はそれを再度呼び出すことです。元)

        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
于 2016-03-29T00:46:47.263 に答える
2

requestAnimationFrame polyfill gibhub ページをご覧になることをお勧めします。これがどのように実装されるかについての議論があります。

于 2012-05-24T12:25:33.110 に答える
2

そのため、さらにテストを行った後、アニメーションが停止するのではなく、実際に問題を引き起こしたのは他のコードであることがわかりました (結局、単純な再帰でした)。問題は、ページからレンダラーの domElement を動的に追加および削除することにありました。それをやめた後、そうする理由が本当になかったので、初期化が行われている場所に一度含めたところ、すべてが正常に機能し始めました。

于 2012-05-24T21:16:45.680 に答える