Reputation: 207
Honorable coders, I use an html5 slideshow where I have added the rotating mesh landscape (https://github.com/jeromeetienne/threex.terrain). Because this animation slows down other part of the slideshow I want to shut it down when I move to the next slide. I can call a function when the next slide is shown, however, I do not know how to shut down the rotation or simply stop the function. I have tried removing the element 'front_id' that contains the rotating landscape but that does not seem to help and looking at the performance log the GPU is running crazy even when the element is deleted. Any solutions?
My updated failed attempt:
<script type="text/javascript">
var id_an;
function run_land(){
var renderer = new THREE.WebGLRenderer({
antialias : true
});
renderer.setSize( window.innerWidth+600, window.innerHeight );
var the_dom = renderer.domElement;
the_dom.id = 'land_id';
document.getElementById('front_id').appendChild(the_dom);
var onRenderFcts= [];
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(25,
window.innerWidth/window.innerHeight, 0.01, 1000);
camera.position.z = 15;
camera.position.y = 2;
scene.fog = new THREE.Fog(0x565656, 10, 45);
;(function(){
var light = new THREE.AmbientLight( 0x202020 );
scene.add( light );
var light = new THREE.DirectionalLight('white', 5);
light.position.set(0.5, 0.0, 2);
scene.add( light );
var light = new THREE.DirectionalLight('white', 0.75*2);
light.position.set(-0.5, -0.5, -2);
scene.add( light );
})()
var heightMap = THREEx.Terrain.allocateHeightMap(512,256);
THREEx.Terrain.simplexHeightMap(heightMap);
var geometry = THREEx.Terrain.heightMapToPlaneGeometry(heightMap);
THREEx.Terrain.heightMapToVertexColor(heightMap, geometry);
var material = new THREE.MeshBasicMaterial({
wireframe: true
});
var mesh = new THREE.Mesh( geometry, material );
mesh.name = 'the_mesh_name';
scene.add( mesh );
mesh.lookAt(new THREE.Vector3(0,1,0));
mesh.scale.y = 4.5;
mesh.scale.x = 5;
mesh.scale.z = 0.30;
mesh.scale.multiplyScalar(10);
onRenderFcts.push(function(delta, now){
mesh.rotation.z += 0.2 * delta;
})
onRenderFcts.push(function(){
renderer.render( scene, camera );
})
var lastTimeMsec= null;
function animate(nowMsec){
requestAnimationFrame( animate );
lastTimeMsec = lastTimeMsec || nowMsec-1000/60;
var deltaMsec = Math.min(200, nowMsec - lastTimeMsec);
lastTimeMsec = nowMsec;
onRenderFcts.forEach(function(onRenderFct){
onRenderFct(deltaMsec/5000, nowMsec/5000);
});
}
id_an = requestAnimationFrame(animate);
}
var end_landscapes = (function() {
return function() {
console.log("the id: "+id_an); //this always returns id_an = 4
cancelAnimationFrame(id_an);
};
})();
</script>
Thanks TheJim01 you are definitely right. Not sure what I am doing wrong. Here I am defining the animationFrame variable globally but still I am unable to cancel it.
Upvotes: 0
Views: 1994
Reputation: 8876
Close, but not quite. Look at what you have here:
function animate(nowMsec) {
requestAnimationFrame(animate);
lastTimeMsec = lastTimeMsec || nowMsec - 1000 / 60;
var deltaMsec = Math.min(200, nowMsec - lastTimeMsec);
lastTimeMsec = nowMsec;
onRenderFcts.forEach(function(onRenderFct) {
onRenderFct(deltaMsec / 5000, nowMsec / 5000);
});
}
id_an = requestAnimationFrame(animate);
You're assigning id_an
with the ID of the first call to requestAnimationFrame
, but you're not assigning it to IDs of the calls inside animate
. Every call to requestAnimationFrame
returns a unique ID, and you need to be able to cancel the most recent one to kill the loop.
Try this:
function animate(nowMsec) {
id_an = requestAnimationFrame(animate);
lastTimeMsec = lastTimeMsec || nowMsec - 1000 / 60;
var deltaMsec = Math.min(200, nowMsec - lastTimeMsec);
lastTimeMsec = nowMsec;
onRenderFcts.forEach(function(onRenderFct) {
onRenderFct(deltaMsec / 5000, nowMsec / 5000);
});
}
animate();
With this small change, id_an
gets updated every frame with the latest ID, so when you call cancelAnimationFrame
it will cancel the most recent one (which is the one you want to cancel).
Also, you don't need to call requestAnimationFrame
to start the loop. Calling animate();
at the end will get things rolling, including subsequent calls to requestAnimationFrame
.
Upvotes: 1