How to Stop a Requestanimationframe Recursion/Loop

How to stop recursive loop with `requestAnimationFrame`

First, it's not really recursive since it queues the callback on the event loop rather than calling the callback directly. So you don't have to worry about running out of memory on the call stack.

To stop calling requestAnimationFrame, you simply don't call it. The question is, when do you want to stop calling it? If you are providing a utility function for someone else, you usually let them dictate when to "unsubscribe" or stop the updates.

private recursiveLoopWithDelay(loopFn: any, delay: number) {
const self = this;
let stamp = Date.now();

function _loop() {
// If we aren't looping anymore, just exit the code.
// Don't requeue requestAnimationFrame
if (!self.isLoopOn) {
return;
}

if (Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}

window.requestAnimationFrame(_loop);
}

window.requestAnimationFrame(_loop);
}

You can also skip binding by using Lexical scope like I've done here. Storing this in a variable self that I can lookup at any point.

How to stop a requestAnimationFrame recursion/loop?

So, after doing some more testing, I've found out that it was, indeed, my other code that posed a problem, not the animation stopping (it was a simple recursion after all). The problem was in dynamically adding and removing the renderer's domElement from the page. After I've stopped doing that, for there was really no reason to do so, and included it once where the initialization was happening, everything started working fine.

Cancel the requestAnimationFrame loop after some time

Just use a variable to reference the current render function and change that variable on the timer event.

Example

var currentFrameRender = animate;  // set current render
requestAnimationFrame(currentFrameRender); // request first frame
setTimeout(() => currentFrameRender = update ,5000); // switch render in 5s
setTimeout(() => currentFrameRender = undefined ,10000); // stop animation in 10s

function animate(){
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(let i = 0; i < circles.length; i++){
circleArray[i].scatter();
}

// request frame only if currentFrameRender is defined
currentFrameRender && requestAnimationFrame(currentFrameRender);
}

function update(){
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(let i = 0; i < circles.length; i++){
circleArray[i].update();
}

// request frame only if currentFrameRender is defined
currentFrameRender && requestAnimationFrame(currentFrameRender);
}

How to stop a requestAnimationFrame on canvas in JavaScript

You can use cancelAnimationFrame() to stop the animation. You can assign requestAnimationFrame() to a variable and then to stop the animation call that variable in the cancel function. You also don't need to call requestAnimationFrame() in the mouseDown function since just calling draw() will trigger it to be activated.

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width" />

<head>
<title>Parking Master LVL. 1</title>
</head>

<body>
<h3 id="header-style">Parking Master</h3>
<p class="paraGraph1">How to play:</p>
<ol id="directions">
<p>1. drive into the Green Outlined Square</p>
<p>2. do not crash through the process or the game ends!</p>
<p>3. press "<span><button style="position: relative;
top: -3px;
color: #11fc05;
border: 2px double #11fc05; width: 1.2em; height: 1.2em;"><span style="position: absolute; left: 4px;top: 0px; font-size: 0.6em;">Park</span></button></span>" when you parked in the correct spot.</p>
</ol>
</body>
<link rel="stylesheet" href="style.css">
<!--Game-->
<canvas id="myCanvas" width="600" height="400" style="border:2px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>

<button style="position:absolute;left:550px;top:600px;" class="buttonDrive" onmousedown="mouseDown()" onmouseup="mouseUp()">Drive</button>

<button class="buttonPark" onclick="parkDetector()" style="position: absolute;left: 550px; top: 540px;"><strong>Park</strong></button>
<div id="Car-Body">
<script>
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
x = 0,
last = performance.now(),
animate;

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.rect(x, 20, 20, 20);
ctx.fillStyle = "#000000";
ctx.fill();
x += 0.5;
animate = requestAnimationFrame(draw);
}
</script>
</div>
<script>
var continueAnimating = true;
var carBody = document.getElementById("Car-Body");
// detect if car is parked
function parkDetector() {
if (carBody > 0) {
// If the car Parked in the correct spot
carIsParked();
}
}
// If the car is not parked in the correct spot
if (carBody < 176) {
function carIsNotParked() {
alert("Hmm... it doesn't seem like you parked!");
}
}

function carIsParked() {
alert("You Parked!");
document.body.innerHTML += p;
document.body.innerHTML += '<button onclick="nextLevel()">Next Level</button>';
}
// Direct the car
var p = '<div></div>';
// Redirect to Next Level
function nextLevel() {
document.getElementsByClassName().innerHTML = '<a href="https://sites.google.com/view/parking-master-lvl2">Next Level</a>';
}

function mouseUp() {
console.log('wow');
cancelAnimationFrame(animate) // if the "Drive" button is let go of, cancel the animation
}

function mouseDown() {
draw();
// if "Drive" is pressed, draw the animation
}
</script>

Can't stop requestAnimationFrame (Javascript/html5: canvas)

var active = true;
function gameloop(){
if(active){
window.requestAnimationFrame(gameloop);
}
}

Why does calling requestAnimationFrame at the beginning of a loop not cause infinite recursion?

Please let me know if I am completely off-base; I haven't used the animation stuff before. An example I saw for using requestAnimationFrame is:

(function animloop(){
requestAnimFrame(animloop);
render();
})();

Are you wondering why animloop as it is passed into requestAnimFrame doesn't cause an infinite loop when it is subsequently called?

This is because this function isn't truly recursive. You might be thinking that animloop is immediately called when you call requestAnimFrame. Not so! requestAnimFrame is asynchronous. So the statements are executed in the order that you see. What this means is that the main thread does not wait for the call to requestAnimFrame to return, before the call to render(). So render() is called almost immediately. However the callback (which in this case is animloop) is not called immediately. It may be called at some point in the future when you have already exited from the first call to animloop. This new call to animloop has its own context and stack since it hasn't been actually called from within the execution context of the first animloop call. This is why you don't end up with infinite recursion and a stack overflow.

Right usage of requestAnimationFrame / cancelAnimationFrame

You should send the id of the requestAnimationFrame you want to cancel into cancelAnimationFrame. That id is a return value of the original requestAnimationFrame.

So request one animation loop:

var id = requestAnimationFrame(cache.mechanism.snowFall);

And to cancel that request:

cancelAnimationFrame(id);

Alternatively, since requestAnimationFrame must be called to keep the loop running, you could use a flag to stop the animation:

// Set an external flag to allow animations to continue
var continueAnimating = true;

function animate()
{
if(continueAnimating)
{
// when continueAnimating is false, this new
// request will not occur and animation stops
requestAnimationFrame(animate);
}
}

// To turn off animation
continueAnimating = false;

How do I stop requestAnimationFrame

var id;

function animate() {

id = requestAnimationFrame( animate );

renderer.render( scene, camera );

}

To cancel

cancelAnimationFrame( id );

three.js r.55

Is requestAnimationFrame implementation's recursive?

This only requests the browser to call your callback before the next rendering loop:

You should call this method whenever you're ready to update your animation onscreen. This will request that your animation function be called before the browser performs the next repaint.

So there is no recursion here, and your function continue with the execution.

You can also cancel the request for your callback with cancelAnimationFrame.

Look here.



Related Topics



Leave a reply



Submit