问题
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.
回答1:
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
回答2:
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
回答3:
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)
};
来源:https://stackoverflow.com/questions/23770521/threejs-stop-rendering