Fabian
Fabian

Reputation: 130

requestAnimationFrame fires far more often than 60 fps

I'm using requestAnimationFrame to animate a part of my page on mousemove. One issue I encountered just now is that it calls the drawing code far more often than the expected 60 times per second (my monitor refresh rate) if the mousemove events happen faster than that.

This seems to depend on the mouse you use, but with my current one I can get easily 10 mousemove events inside the same frame if I move it relatively fast. My understanding was that requestAnimationFrame should only trigger the drawing function once per Frame, no matter how often it is called.

Now, calling my drawing code 10 times inside one frame is obviously terrible for performance, so I need to get rid of this. Do I have to manually handle this by design? Is my understanding of requestAnimationFrame wrong and this is the correct behaviour, or what am I missing here? How is requestAnimationFrame supposed to work?

Upvotes: 2

Views: 764

Answers (1)

Kaiido
Kaiido

Reputation: 137171

My understanding was that requestAnimationFrame should only trigger the drawing function once per Frame, no matter how often it is called.

This is where your understanding misled you.

requestAnimationFrame method will actually stack every functions and execute them in the same frame.

So if you do call 30 times requestAnimationFrame(func) in the same frame, then func will be called 30 times at next frame. These functions even seem to be merged into the same call since they do share the same time parameter.

var funcA = function(time) {
  snippet.log('funcA executed at ' + time);
  snippet.log('exact time: ' + performance.now())
}
var funcB = function(time) {
  snippet.log('funcB executed at ' + time);
  snippet.log('exact time: ' + performance.now())
}


snippet.log('funcA stacked at ' + performance.now())
requestAnimationFrame(funcA);
// block the process for some time
var i = 0;
while (i++ < 10000000) {}

snippet.log('funcB stacked at ' + performance.now())
requestAnimationFrame(funcB);
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

To avoid it, e.g. to make a debounce, you need to use some flagging, that you will release when the rAF executes.

Upvotes: 2

Related Questions