Craig Gidney Craig Gidney - 1 month ago 6
Javascript Question

HTML5 canvas not showing redrawn content during mouse drags

I have a circuit simulator that redraws as you drag things around on an HTML5 canvas.

I've noticed that, sometimes, it fails to redraw during drags. It holds the last drawn frame until I stop moving the mouse, then starts showing updated content.

At first I thought this might be some kind of issue with the code I use the throttle the draws below 60fps. Maybe timer events were being swamped out by higher priority UI events or something like that. But I profiled the code in Chrome, and the profiler confirms the draw code is being called and finishing in a reasonable amount of time.

Here's a screenshot from an example profile I collected while dragging with the issue happening. Note the draw code finishing within 5ms, with plenty of idle time:

Flame chart

So mostly I'm stumped and need ideas of what to check.

What are some common reasons for redraws not to show when they are being triggered by user actions?

Answer

Use requestAnimationFrame instead of setTimeout.

During my testing (Chrome, Windows 10), I found that if I just spun the mouse wheel up and down quickly then I could prevent setTimeout callbacks from running until I stopped. That makes setTimeout a really bad idea when it comes to canvas animations. I switched the throttling code to using a requestAnimationFrame cycle, that just kept rescheduling itself until the cooldown period was over, and lag decreased noticeably.