There's one main problem with ResizeObserver and rendering using canvas:
people typically use requestAnimationFrame for animating
ResizeObserver is used for handling size changes
ResizeObserver callbacks run after animation frame callbacks
A user's animation frame loop typically includes an update to canvas (f.e. WebGL)
when ResizeObserver runs after animation frames, a second render-to-canvas will be needed so that the drawing will be correct, or else the problem of canvas flickering will happen due to resize clearing canvas pixels before browser paint. See:
This is not possible, because ResizeObserver callbacks run after animation frames
A new animation frame can be requested so that resize happens in the next animation frame before draw, but then the drawing will always be one frame behind, making resize look clunky
skip drawing in rAF, draw in RO callback
This is not possible. The point of RO is to detect size changes, and we don't know about size changes until RO callbacks run. There's no way to know if ResizeObserver has records queued, so that we can conditionally skip drawing in rAF and instead draw in RO callbacks.
So, how do we know that we need to avoid drawing in rAF, and instead draw in an RO callback?
That's where this issue comes in.
If we had ResizeObserver.takeRecords(), we could get the records, run the resize logic in rAF, and then draw.
If we had ResizeObserver.hasRecords(), we could skip drawing in rAF, then let the draw happen in the following RO callback.
Spec: https://drafts.csswg.org/resize-observer/#resize-observer-interface
There's one main problem with ResizeObserver and rendering using canvas:
requestAnimationFrame
for animatingSHOW_FLICKER_PROBLEM
totrue
at the bottom, then repeatedly resize the example)So, how do we know that we need to avoid drawing in rAF, and instead draw in an RO callback?
That's where this issue comes in.
If we had
ResizeObserver.takeRecords()
, we could get the records, run the resize logic in rAF, and then draw.If we had
ResizeObserver.hasRecords()
, we could skip drawing in rAF, then let the draw happen in the following RO callback.Note, if we get other observers like
ComputedStyleObserver
andBoundingClientRectObserver
orClientRectObserver
for short, the same problem will exist with those if they run after rAF but before browser paint, and they should also havetakeRecords
and preferablyhasRecords
.An alternative API that would help with these problems would be
requestFinalFrame
orrequestPaintFrame
.The convention for web developers would become:
requestAnimationFrame
ResizeObserver
,ComputedStyleObserver
,MutationObserver
, etc)requestFinalFrame
(orrequestPaintFrame
or whatever name we come up with) to apply final drawing/rendering.