最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ThreeJS Stop Rendering - Stack Overflow

programmeradmin3浏览0评论

I am working with ThreeJS on a basic 3d scene that has OrbitControls. Everything works great, except it causes my entire site to lag, as it is looping itself even when the user is not looking at it. I want a function that I can call to start and stop the rendering when certain conditions are met (in this case, the user isn't viewing the canvas). I have a start function that works just fine, but the stop function does not seem to be working, as my site goes unbearably slow after ThreeJS has initialized.

I have looked and looked for a solution to this problem, and have found a couple 'solutions', but for whatever reason they do not work with my application. My assumption is that these solutions are from old versions of ThreeJS.

Here is my code in my main.js file:

var scene, 
    camera, 
    controls,
    render,
    requestId = undefined;


function init() {
    scene = new THREE.Scene();
    var threeJSCanvas = document.getElementById("threeJS");
    camera = new THREE.PerspectiveCamera( 75, threeJSCanvas.width / threeJSCanvas.height, 0.1, 1000 );

    controls = new THREE.OrbitControls( camera );

    // Controls and Camera settings

    // Create Geometry.

}

function render() {
    requestId =  requestAnimationFrame(render);
    renderer.render(scene, camera);

}

function start() {
    render();
}

function stop() {
   window.cancelAnimationFrame(requestId);
   requestId = undefined;


}

In my other javascript file, there is a conditional inside of my pageChange function (this is a multipage app), that looks like the following:

if (page == 5) { // The page with the canvas on it
    if (!locationsRendered) {
    init();
    locationsRendered = true;
}
} else { // If the page is not the page with the canvas on it
    if (locationsRendered) {
        stop();
    }
}

locationsRendered is initialized earlier in this second javascript file in the local scope.

Any help would be much appreciated, as I can not let this simple 3D scene lag my entire app after it has been loaded. It's just not realistic.

I am working with ThreeJS on a basic 3d scene that has OrbitControls. Everything works great, except it causes my entire site to lag, as it is looping itself even when the user is not looking at it. I want a function that I can call to start and stop the rendering when certain conditions are met (in this case, the user isn't viewing the canvas). I have a start function that works just fine, but the stop function does not seem to be working, as my site goes unbearably slow after ThreeJS has initialized.

I have looked and looked for a solution to this problem, and have found a couple 'solutions', but for whatever reason they do not work with my application. My assumption is that these solutions are from old versions of ThreeJS.

Here is my code in my main.js file:

var scene, 
    camera, 
    controls,
    render,
    requestId = undefined;


function init() {
    scene = new THREE.Scene();
    var threeJSCanvas = document.getElementById("threeJS");
    camera = new THREE.PerspectiveCamera( 75, threeJSCanvas.width / threeJSCanvas.height, 0.1, 1000 );

    controls = new THREE.OrbitControls( camera );

    // Controls and Camera settings

    // Create Geometry.

}

function render() {
    requestId =  requestAnimationFrame(render);
    renderer.render(scene, camera);

}

function start() {
    render();
}

function stop() {
   window.cancelAnimationFrame(requestId);
   requestId = undefined;


}

In my other javascript file, there is a conditional inside of my pageChange function (this is a multipage app), that looks like the following:

if (page == 5) { // The page with the canvas on it
    if (!locationsRendered) {
    init();
    locationsRendered = true;
}
} else { // If the page is not the page with the canvas on it
    if (locationsRendered) {
        stop();
    }
}

locationsRendered is initialized earlier in this second javascript file in the local scope.

Any help would be much appreciated, as I can not let this simple 3D scene lag my entire app after it has been loaded. It's just not realistic.

Share Improve this question asked May 20, 2014 at 21:45 BjornirBjornir 1151 gold badge1 silver badge6 bronze badges 4
  • You scene appears to be static. Is that correct? If so, you do not need to re-render it 60 times a second. – WestLangley Commented May 20, 2014 at 22:03
  • That is very correct, nothing is animated, except for the controls. For some reason I thought that in order for the controls to operate smoothly, it needed to render at 60fps. I am going to fix that and will report back! – Bjornir Commented May 20, 2014 at 22:13
  • Just add controls.addEventListener( 'change', render ); – WestLangley Commented May 20, 2014 at 22:16
  • That helped tremendously with performance. Thank you so much! Now I just need to modify a couple things to hide the canvas or atleast disable it's controls when they are not needed. Is there any way you could convert you response to an answer so I can choose it as the best answer? – Bjornir Commented May 20, 2014 at 23:38
Add a comment  | 

3 Answers 3

Reset to default 13

If your scene is static, there is no reason for an animation loop. You only need to re-render when the camera moves due to a mouse or touch event.

Just use this pattern:

controls = new THREE.OrbitControls( camera, renderer.domElement );

controls.addEventListener( 'change', render );

function render() {

    renderer.render( scene, camera );

}

three.js r.67

I was using trackball controls in my scene and therefore couldn't use the solution above (as the trackball controls continue updating after mouse events finish triggering).

To solve this problem, I used:

function animate() {
  renderer.render(scene, camera);
  controls.update();
}
renderer.setAnimationLoop(animate);

That runs the animation loop indefinitely. To pause the animation, one can then specify null as the animation loop:

renderer.setAnimationLoop(null);        // pause the animation

And to resume the animation, just pass the animation loop again:

renderer.setAnimationLoop(animate);     // resume the animation

An alternative solution to completely stopping the render loop is to reduce the frames per second rate and thereby reducing resource consumption.

This approach is particularly useful if you need responsive update on your scene while not necessarily animating, but also need to snap back normal speeds when you need to.

a simple setTimout() achieves this nicely.

var fps 10;

function render() {

   //reduce framerate
   setTimeout(()=>{

        requestAnimationFrame(render);

        //must be called to enable rotating
        controls.update();
        renderer.render(scene, camera);


   }, 1000/fps)

};
发布评论

评论列表(0)

  1. 暂无评论