From 825c0aa19417b51a0901304ea8e78e9a7504cfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Mon, 25 May 2026 19:16:17 -0400 Subject: [PATCH] fix(studio): use declared dimensions for overlay scale during GSAP playback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When GSAP applies transforms (scale, translate) to the root composition element during playback, rootRect.width/height from getBoundingClientRect() changes to reflect the transformed size. The overlay scale calculation (rootScaleX/Y = iframeRect / rootRect) then produces wrong values, causing overlays to appear at incorrect positions during animated playback — especially visible during scroll animations (y transform) and entrance animations (scale transform). Fix: use the composition's declared data-width/data-height attributes for scale calculation. These are the canonical dimensions that don't change with GSAP transforms. Falls back to rootRect dimensions when the attributes aren't present (non-composition elements). --- .../src/components/editor/domEditOverlayGeometry.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/studio/src/components/editor/domEditOverlayGeometry.ts b/packages/studio/src/components/editor/domEditOverlayGeometry.ts index 647c92174..56620788d 100644 --- a/packages/studio/src/components/editor/domEditOverlayGeometry.ts +++ b/packages/studio/src/components/editor/domEditOverlayGeometry.ts @@ -92,9 +92,16 @@ export function toOverlayRect( const root = doc?.querySelector("[data-composition-id]") ?? doc?.documentElement ?? null; const rootRect = root?.getBoundingClientRect(); - const rootWidth = rootRect?.width; - const rootHeight = rootRect?.height; - if (!rootWidth || !rootHeight) return null; + // Use the composition's declared dimensions (data-width/data-height) for scale + // calculation instead of rootRect.width/height. When GSAP applies transforms + // (scale, translate) to the root element, rootRect dimensions change but the + // composition's canonical size stays the same. Using rootRect causes overlay + // misalignment during animated playback. + const declaredWidth = readPositiveDimension(root?.getAttribute("data-width") ?? null); + const declaredHeight = readPositiveDimension(root?.getAttribute("data-height") ?? null); + const rootWidth = declaredWidth ?? rootRect?.width; + const rootHeight = declaredHeight ?? rootRect?.height; + if (!rootWidth || !rootHeight || !rootRect) return null; const elementRect = element.getBoundingClientRect(); const rootScaleX = iframeRect.width / rootWidth;