Pausing requestAnimationFrame

This is a response to a YouTube question where the question is around how you would pause a requestAnimationFrame loop. Here is something that has worked for me:

var isRunning = true;

function togglePause() {
  // toggle the value of isRunning
  isRunning = !isRunning;

  // call animate() if working
  if (isRunning) {
    animate();
  }
}

function animate() {

  document.body.textContent = Math.random() * 10000;

  // if not paused, do epic things!
  if (isRunning) {
    requestAnimationFrame(animate);
  }
}

//togglePause();

animate();

You can uncomment the togglePause() call towards the end to see this at work. There is no built-in “pause” functionality for requestAnimationFrame, so that is why I am taking this approach.

Cheers,
Kirupa :slight_smile:

I was thinking something like this would also work:

let rafID

function animate(){
    document.body.textContent = Math.random() * 10000
    rafID = requestAnimationFrame(animate)
}

function pause(){
    cancelAnimationFrame(rafID)
}
1 Like

Do you know if it makes a difference whether the call to requestAnimationFrame is at the beginning or the end of the animate() function? I thought the beginning of the function was an odd place to put it, but all the examples I looked at the other day had it there.

It doesn’t matter. Its only defining a callback which doesn’t cause anything to happen until the next animation loop when the callback (animate) is called. I think having it at the end of the function makes a little more sense (to me) since it represents something that happens after all of this code is run, so it better matches the progression of execution (plus it allows that code to set values for things like isRunning), but it doesn’t have to be.

Maybe it lets the caller get a better spot in the queue than any callees? That’s phrased poorly, so here’s an example:

foo()

function foo(){
    requestAnimationFrame(foo)
    bar() // foo wants to be scheduled before bar
}

function bar(){
    requestAnimationFrame(bar)
}

Just speculating. Also, if your function takes 20ms to run, and the scheduler is using some time-based weights, it’s maybe better to call early on.

Edit: It seems like there’d be a lot of performant ways to cheat if there were some heuristic that assumed that functions would call rAF near their end, so it’d make sense to try to game that heuristic. I certainly don’t know that that’s a real heuristic, but it seems mildly reasonable.

@alltom

Thanks for the speculation, all. :slight_smile: Another thing occurred to me after reading your replies: maybe it’s defensive programming? If the scheduling is the same regardless of when you call requestAnimationFrame, from a flow control point of view, this:

function foo() {
  requestAnimationFrame(foo);
  // ... work ...
}

could be shorthand for this:

function foo() {
  try {
    // ... work ...
  } finally {
    requestAnimationFrame(foo);
  }
}

I find that a bit too defensive haha :stuck_out_tongue:

1 Like