refactor: resize performance
This commit is contained in:
40
frontend/src/lib/sharedResizeObserver.ts
Normal file
40
frontend/src/lib/sharedResizeObserver.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user