diff --git a/src/components/effects/GradientBlinds.tsx b/src/components/effects/GradientBlinds.tsx index 9f3b787..7550beb 100644 --- a/src/components/effects/GradientBlinds.tsx +++ b/src/components/effects/GradientBlinds.tsx @@ -280,18 +280,36 @@ void main() { const mesh = new Mesh(gl, { geometry, program }); meshRef.current = mesh; - const resize = () => { - const rect = container.getBoundingClientRect(); - rectRef.current = rect; + const resize = (entries?: ResizeObserverEntry[]) => { + let width, height; + + if (entries && entries.length > 0) { + const entry = entries[0]; + width = entry.contentRect.width; + height = entry.contentRect.height; + // Optimization: Defer calling getBoundingClientRect (which forces layout) + // to the next frame, since ResizeObserver runs after layout but before paint. + requestAnimationFrame(() => { + if (rendererRef.current) { + rectRef.current = container.getBoundingClientRect(); + } + }); + } else { + const rect = container.getBoundingClientRect(); + rectRef.current = rect; + width = rect.width; + height = rect.height; + } + if (typeof window !== 'undefined') { isMobileRef.current = window.innerWidth <= 768; scrollPosRef.current = { x: window.scrollX, y: window.scrollY }; } - renderer.setSize(rect.width, rect.height); + renderer.setSize(width, height); uniforms.iResolution.value = [gl.drawingBufferWidth, gl.drawingBufferHeight, 1]; if (blindMinWidth && blindMinWidth > 0) { - const maxByMinWidth = Math.max(1, Math.floor(rect.width / blindMinWidth)); + const maxByMinWidth = Math.max(1, Math.floor(width / blindMinWidth)); const effective = blindCount ? Math.min(blindCount, maxByMinWidth) : maxByMinWidth; uniforms.uBlindCount.value = Math.max(1, effective);