Browse Source
refactor(sync): Extract animation loop into sync module
refactor(sync): Extract animation loop into sync module
Moves the main animationLoop function from index.html into a dedicated src/sync.js module. This change isolates the core playback, clock management, and video resynchronization logic into a single, focused file. The main script in index.html now imports and calls this function, simplifying its responsibilities and preparing for the final wiring step.refactor/modularize
2 changed files with 60 additions and 32 deletions
@ -0,0 +1,52 @@ |
|||
import { appState } from './state.js'; |
|||
import { videoPlayer, speedSlider, offsetInput, stopBtn, updateFrame, updateCanDisplay, updateDebugOverlay } from './dom.js'; |
|||
import { findRadarFrameIndexForTime } from './utils.js'; |
|||
|
|||
/** |
|||
* The main animation loop that drives the synchronized playback. |
|||
* It calculates the current media time based on performance.now() for a smooth clock, |
|||
* finds the corresponding radar frame, and handles resynchronization with the video element. |
|||
*/ |
|||
export function animationLoop() { |
|||
if (!appState.isPlaying) return; |
|||
|
|||
const playbackSpeed = parseFloat(speedSlider.value); |
|||
const elapsedRealTime = performance.now() - appState.masterClockStart; |
|||
const currentMediaTime = appState.mediaTimeStart + (elapsedRealTime / 1000) * playbackSpeed; |
|||
|
|||
// Update radar frame based on the master clock
|
|||
if (appState.vizData && appState.videoStartDate) { |
|||
const offsetMs = parseFloat(offsetInput.value) || 0; |
|||
const targetRadarTimeMs = (currentMediaTime * 1000) + offsetMs; |
|||
const targetFrame = findRadarFrameIndexForTime(targetRadarTimeMs, appState.vizData); |
|||
if (targetFrame !== appState.currentFrame) { |
|||
updateFrame(targetFrame, false); |
|||
} |
|||
} |
|||
|
|||
// Periodically check for drift between master clock and video element
|
|||
const now = performance.now(); |
|||
if (now - appState.lastSyncTime > 500) { |
|||
const videoTime = videoPlayer.currentTime; |
|||
const drift = Math.abs(currentMediaTime - videoTime); |
|||
if (drift > 0.15) { // Resync if drift is > 150ms
|
|||
console.warn(`Resyncing video. Drift was: ${drift.toFixed(3)}s`); |
|||
videoPlayer.currentTime = currentMediaTime; |
|||
} |
|||
appState.lastSyncTime = now; |
|||
} |
|||
|
|||
// Stop playback at the end of the video
|
|||
if (currentMediaTime >= videoPlayer.duration) { |
|||
stopBtn.click(); |
|||
return; |
|||
} |
|||
|
|||
// Update other UI elements
|
|||
updateCanDisplay(currentMediaTime); |
|||
updateDebugOverlay(currentMediaTime); |
|||
if (appState.speedGraphInstance) appState.speedGraphInstance.redraw(); |
|||
|
|||
// Request the next frame
|
|||
requestAnimationFrame(animationLoop); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue