From 2391f3a889f578bb5c4d279ee34286c57f4e5472 Mon Sep 17 00:00:00 2001 From: rakadu1 Date: Fri, 20 Feb 2026 15:04:45 +0530 Subject: [PATCH] feat(ui): improve IFT graph scaling animation and performance - Implemented smooth dynamic scaling for the Inter-Frame Timing (IFT) graph that remains active even when playback is paused. - Added a conditional `requestAnimationFrame` loop to ensure the graph scale converges smoothly to the target value during scrubbing or pause states. - Tuned animation speeds: fast convergence (0.1 smoothing) during playback, slower (0.033) when paused for a more polished visual transition. - Fixed a layout thrashing (forced reflow) performance issue in `updatePersistentOverlays` by reading `clientWidth` before writing text updates to the DOM. --- steps/src/dom.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/steps/src/dom.js b/steps/src/dom.js index 16261fd..e9d663b 100644 --- a/steps/src/dom.js +++ b/steps/src/dom.js @@ -353,6 +353,14 @@ export function updatePersistentOverlays(currentMediaTime) { }; } + // --- PERFORMANCE FIX: Read layout BEFORE writing to DOM --- + // Reading clientWidth here avoids "Forced Reflow" (Layout Thrashing) because + // we haven't dirtied the layout with text updates yet in this frame. + let currentCanvasWidth = 0; + if (overlayCache && overlayCache.dotCanvas) { + currentCanvasWidth = overlayCache.dotCanvas.clientWidth; + } + // --- 1. Smart Smooth Zoom Logic --- // Use pre-calculated maxWindowIFT (computed in fileParsers.js) for O(1) performance. const maxWindowIFT = currentRadarFrame.maxWindowIFT || 0; @@ -367,9 +375,16 @@ export function updatePersistentOverlays(currentMediaTime) { } // Smooth Interpolation (Lerp) - // Move current scale 10% of the way to the target per frame. - const smoothingFactor = 0.1; + // Move current scale towards the target. + // If playing, use 0.1 (fast). If stopped, use 0.033 (slow, ~3x slower). + const smoothingFactor = appState.isPlaying ? 0.1 : 0.033; appState.currentGraphScale += (targetMsPerBlock - appState.currentGraphScale) * smoothingFactor; + + // If the scale hasn't converged yet and we are NOT playing (main loop not running), + // request another frame to continue the smoothing animation. + if (!appState.isPlaying && Math.abs(targetMsPerBlock - appState.currentGraphScale) > 0.01) { + requestAnimationFrame(() => updatePersistentOverlays(videoPlayer.currentTime)); + } // Use the smoothed value for drawing const msPerBlock = appState.currentGraphScale; @@ -399,9 +414,8 @@ export function updatePersistentOverlays(currentMediaTime) { let isResized = false; if (dotCanvas) { - const clientWidth = dotCanvas.clientWidth; - if (dotCanvas.width !== clientWidth) { - dotCanvas.width = clientWidth; + if (dotCanvas.width !== currentCanvasWidth) { + dotCanvas.width = currentCanvasWidth; isResized = true; } }