From 63d06540f44e8547d50dbd92eebb21bf84c27acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Tue, 2 Jun 2026 19:43:45 -0400 Subject: [PATCH] fix(studio): use 0.1% precision for keyframe placement instead of 1% Math.round to integer percentages caused visible offset between the playhead and the keyframe diamond at higher zoom levels. Now rounds to 1 decimal place (e.g., 16.3% instead of 16%) for sub-second precision across all keyframe creation paths. --- packages/studio/src/components/TimelineToolbar.tsx | 4 ++-- packages/studio/src/components/editor/PropertyPanel.tsx | 2 +- packages/studio/src/hooks/gsapRuntimeBridge.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/studio/src/components/TimelineToolbar.tsx b/packages/studio/src/components/TimelineToolbar.tsx index 05dafd9301..d280d07337 100644 --- a/packages/studio/src/components/TimelineToolbar.tsx +++ b/packages/studio/src/components/TimelineToolbar.tsx @@ -110,7 +110,7 @@ function useKeyframeToggle(session?: DomEditSessionSlice) { const elDuration = Number.parseFloat(sel.dataAttributes?.duration ?? "1") || 1; const pct = elDuration > 0 - ? Math.max(0, Math.min(100, Math.round(((currentTime - elStart) / elDuration) * 100))) + ? Math.max(0, Math.min(100, Math.round(((currentTime - elStart) / elDuration) * 1000) / 10)) : 0; state = kfAnim.keyframes.keyframes.some((k) => Math.abs(k.percentage - pct) <= 1) ? "active" @@ -126,7 +126,7 @@ function useKeyframeToggle(session?: DomEditSessionSlice) { const elDuration = Number.parseFloat(sel.dataAttributes?.duration ?? "1") || 1; const pct = elDuration > 0 - ? Math.max(0, Math.min(100, Math.round(((t - elStart) / elDuration) * 100))) + ? Math.max(0, Math.min(100, Math.round(((t - elStart) / elDuration) * 1000) / 10)) : 0; const existing = kfAnim.keyframes.keyframes.find( (k) => Math.abs(k.percentage - pct) <= 1, diff --git a/packages/studio/src/components/editor/PropertyPanel.tsx b/packages/studio/src/components/editor/PropertyPanel.tsx index e9e3f3c1d5..19dc6e8d92 100644 --- a/packages/studio/src/components/editor/PropertyPanel.tsx +++ b/packages/studio/src/components/editor/PropertyPanel.tsx @@ -239,7 +239,7 @@ export const PropertyPanel = memo(function PropertyPanel({ const parsed = parsePxMetricValue(nextValue); if (parsed == null) return; if (gsapKeyframes && gsapAnimId && onAddKeyframe) { - const pct = Math.max(0, Math.min(100, Math.round(currentPct))); + const pct = Math.max(0, Math.min(100, Math.round(currentPct * 10) / 10)); onAddKeyframe(gsapAnimId, pct, axis, parsed); return; } diff --git a/packages/studio/src/hooks/gsapRuntimeBridge.ts b/packages/studio/src/hooks/gsapRuntimeBridge.ts index b751351371..a8841318d5 100644 --- a/packages/studio/src/hooks/gsapRuntimeBridge.ts +++ b/packages/studio/src/hooks/gsapRuntimeBridge.ts @@ -95,7 +95,7 @@ function computeCurrentPercentage(selection: DomEditSelection): number { const elDuration = Number.parseFloat(selection.dataAttributes?.duration ?? "1") || 1; const currentTime = usePlayerStore.getState().currentTime; return elDuration > 0 - ? Math.max(0, Math.min(100, Math.round(((currentTime - elStart) / elDuration) * 100))) + ? Math.max(0, Math.min(100, Math.round(((currentTime - elStart) / elDuration) * 1000) / 10)) : 0; }