diff --git a/steps/src/dom.js b/steps/src/dom.js index 6a1051b..f7065b4 100644 --- a/steps/src/dom.js +++ b/steps/src/dom.js @@ -250,6 +250,9 @@ function getCurrentColorMode() { return "Default"; // The default mode when no specific color toggle is checked } +// Cache for DOM elements to avoid querySelector/getElementById every frame +let overlayCache = null; + // Cache for conditional rendering let lastDrawnFrame = -1; let lastDrawnScale = -1; @@ -289,12 +292,31 @@ export function updatePersistentOverlays(currentMediaTime) { const interFrameTime = currentRadarFrame.interFrameTime; const iftColor = getTimingColor(interFrameTime); - // --- OPTIMIZATION: One-time DOM Setup --- - if (!document.getElementById("ift-dot-matrix")) { + // --- OPTIMIZATION: One-time DOM Setup & Caching --- + if (!overlayCache) { radarInfoOverlay.innerHTML = ` -
+
+ Frame: + | Motion State: + | FPS: + | Color Mode: + | Drift: + | Δt: + | Scale: +
`; + + overlayCache = { + frame: document.getElementById("ov-frame"), + motion: document.getElementById("ov-motion"), + fps: document.getElementById("ov-fps"), + mode: document.getElementById("ov-mode"), + drift: document.getElementById("ov-drift"), + ift: document.getElementById("ov-ift"), + scale: document.getElementById("ov-scale"), + dotCanvas: document.getElementById("ift-dot-matrix") // Cache canvas too + }; } // --- 1. Smart Smooth Zoom Logic --- @@ -318,23 +340,30 @@ export function updatePersistentOverlays(currentMediaTime) { // Use the smoothed value for drawing const msPerBlock = appState.currentGraphScale; - // --- Update Text Content Efficiently --- - const textContainer = document.getElementById("radar-text-content"); - if (textContainer) { - textContainer.innerHTML = ` - Frame: ${appState.currentFrame + 1} - | Motion State: ${motionState} - | FPS: ${fps.toFixed(1)} - | Color Mode: ${colorMode} - | Drift: ${driftMs.toFixed(0)}ms - | Δt: ${interFrameTime.toFixed(0)}ms`; + // --- Update Text Content Efficiently (Zero Garbage) --- + if (overlayCache) { + overlayCache.frame.textContent = appState.currentFrame + 1; + overlayCache.motion.textContent = motionState; + + overlayCache.fps.textContent = fps.toFixed(1); + overlayCache.fps.style.color = fpsColor; + + overlayCache.mode.textContent = colorMode; + + overlayCache.drift.textContent = driftMs.toFixed(0) + "ms"; + overlayCache.drift.style.color = driftColor; + + overlayCache.ift.textContent = interFrameTime.toFixed(0) + "ms"; + overlayCache.ift.style.color = iftColor; + + overlayCache.scale.textContent = "1:" + msPerBlock.toFixed(1) + "ms"; } // --- Draw Optimized Square Block Matrix Graph --- // CONDITIONAL RENDER: Only redraw if frame changed or scale changed significantly if (appState.currentFrame !== lastDrawnFrame || Math.abs(msPerBlock - lastDrawnScale) > 0.01) { - const dotCanvas = document.getElementById("ift-dot-matrix"); + const dotCanvas = overlayCache.dotCanvas; // Use cached reference if (dotCanvas) { const ctx = dotCanvas.getContext("2d"); const w = dotCanvas.width;