2

I have a dragging library which moves the element on every mousemove. As we all know, mousemove fires quite often and thus forces the browser into repaints. This could be solved, by do the actual moving in requestAnimationFrame.

Is it a useful thing to do? Will it increase performance and decrease paint events? Are there any issues I didnt think off?

Fuzzyma
  • 7,619
  • 6
  • 28
  • 60
  • Personally I've not done any benchmarking, but for requestanimationframe you'd still be using an event listener for the mouse movement and just using the requireanimationframe api to deliver the X/Y transform at 60fps right? So off the top of my head I don't see how that would reduce any of the overhead on the compositor thread. Now in contrast though if you utilized a [debounce](https://css-tricks.com/debouncing-throttling-explained-examples/) on the event handling itself, than I could see improving perf more than just changing how you're handling the movement of the element. +1 though! – Chris W. Feb 24 '20 at 22:33
  • @ChrisW. debouncing would still call a handler on every mousemove although it would be a performant one. Same is true for dragging. You would only save the coordinates of the mouse, cancel the last frame and request a new one. So the actual dom operation is skipped and delays until the frame happens. Since the dom is slow I _thought_ it would give me a performance boost with the nice sideeffect, that I do all dom changes in the frame and not somewhere random – Fuzzyma Feb 24 '20 at 22:36
  • Here's an idea: use events to track only the cursor position (store in a global), then implement a dragging loop with RAF (start and end on the standard events). Many events are all used, and your render gets the latest possible data. credit: https://stackoverflow.com/questions/2601097/how-to-get-the-mouse-position-without-events-without-moving-the-mouse – Graham P Heath Feb 24 '20 at 23:47
  • @GrahamPHeath storing in a global when the target is an open source libraray is pretty bad :D. Beside that, looks similar to my idea. Thanks! – Fuzzyma Feb 25 '20 at 00:21

1 Answers1

1

Depends on the browser and the use case.

It is now asked by the specs that browsers do threshold themselves UI events (among which the mouse events).

Implementations are encouraged to determine the optimal frequency rate to balance responsiveness with performance.

Chrome and Firefox do this, firing these events only at screen refresh rate, just before requestAniamtionFrame callbacks fire.
So in these browsers, you won't win anything by doing so, but you won't lose much either.

Safari still fires as many such events as the device emits, so in this browser you'll win by maintaining your own threshold.

(Note that if you wish to unleash this threshold, you'll need to use pointerevents instead.)


Now, this is useful to avoid uselessly calculating things that will get discarded by next calls before it can get painted.
The painting will always be throttled to the refresh rate of your screen (just after the requestAnimationFrame callbacks fire).
So it's up to you to determine if you wish to apply that threshold or not.
For instance it can make sense to update a list of points as fast as possible, but to wait the requestAnimationFrame callback to actually make DOM changes or draw anything.

From the little you said about your case, it seems though that you may indeed win by waiting for requestAnimationFrame callbacks, only because you may be modifying the box model of your CSSOM.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • yes right, paintings happen at 60fps anyway. So whats actually slowing down the browser are unneeded dom changes. Interesting though, that FF already threshold mouseevents. Good answer! – Fuzzyma Feb 26 '20 at 00:02