refactor: resize performance

This commit is contained in:
2026-03-12 18:28:31 +01:00
parent a0bf9c6b70
commit e9ed508bfc
3 changed files with 64 additions and 35 deletions

View File

@@ -0,0 +1,40 @@
/**
* Single shared ResizeObserver to avoid one observer per element (memory and overhead).
* Callbacks are throttled to at most once per animation frame per element.
*/
type Size = { width: number; height: number }
const callbacks = new Map<Element, (size: Size) => void>()
const rafScheduled = new Set<Element>()
let observer: ResizeObserver | null = null
function getObserver(): ResizeObserver {
if (!observer) {
observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const cb = callbacks.get(entry.target)
if (!cb || rafScheduled.has(entry.target)) continue
rafScheduled.add(entry.target)
const { width, height } = entry.contentRect
requestAnimationFrame(() => {
rafScheduled.delete(entry.target)
callbacks.get(entry.target)?.({
width: Math.round(width),
height: Math.round(height),
})
})
}
})
}
return observer
}
export function observeResize(el: Element, callback: (size: Size) => void): () => void {
callbacks.set(el, callback)
getObserver().observe(el)
return () => {
callbacks.delete(el)
getObserver().unobserve(el)
}
}