diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-12 13:26:22 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-12 13:26:22 +0100 |
| commit | a27925e8cbe97b3219437608b40432e886782316 (patch) | |
| tree | 124cf8224177332921490c3c689c633de5ab5558 | |
| parent | 82d34d198b3c916df4d5d39142095edb410e7500 (diff) | |
Timeline editor: fix seek position when zoomed
Use helper functions (beatsToTime, timeToBeats) consistently in click
handlers. Fixes red cursor jumping to wrong position during seek.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| -rw-r--r-- | tools/timeline_editor/index.html | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/tools/timeline_editor/index.html b/tools/timeline_editor/index.html index 2c66ddd..402c580 100644 --- a/tools/timeline_editor/index.html +++ b/tools/timeline_editor/index.html @@ -852,15 +852,15 @@ if (!state.audioBuffer) return; const rect = dom.waveformContainer.getBoundingClientRect(); const clickX = e.clientX - rect.left + dom.timelineContent.scrollLeft; - const clickTime = (clickX / state.pixelsPerSecond) * 60.0 / state.bpm; + const clickBeats = clickX / state.pixelsPerSecond; + const clickTime = beatsToTime(clickBeats); const wasPlaying = state.isPlaying; if (wasPlaying) stopPlayback(false); state.playbackOffset = Math.max(0, Math.min(clickTime, state.audioDuration)); - const clickBeats = state.playbackOffset * state.bpm / 60.0; - dom.playbackTime.textContent = `${state.playbackOffset.toFixed(2)}s (${clickBeats.toFixed(2)}b)`; - const indicatorX = clickBeats * state.pixelsPerSecond; - dom.playbackIndicator.style.left = `${indicatorX}px`; - dom.waveformPlaybackIndicator.style.left = `${indicatorX}px`; + const pausedBeats = timeToBeats(state.playbackOffset); + dom.playbackTime.textContent = `${state.playbackOffset.toFixed(2)}s (${pausedBeats.toFixed(2)}b)`; + const indicatorX = pausedBeats * state.pixelsPerSecond; + dom.playbackIndicator.style.left = dom.waveformPlaybackIndicator.style.left = `${indicatorX}px`; if (wasPlaying) await startPlayback(); }); @@ -917,15 +917,16 @@ if (e.target !== dom.timeline) return; const timelineRect = dom.timeline.getBoundingClientRect(); const clickX = e.clientX - timelineRect.left + dom.timelineContent.scrollLeft; - const clickBeats = clickX / state.pixelsPerSecond, clickTime = clickBeats * 60.0 / state.bpm; + const clickBeats = clickX / state.pixelsPerSecond; + const clickTime = beatsToTime(clickBeats); if (state.audioBuffer) { const wasPlaying = state.isPlaying; if (wasPlaying) stopPlayback(false); state.playbackOffset = Math.max(0, Math.min(clickTime, state.audioDuration)); - const pausedBeats = state.playbackOffset * state.bpm / 60.0; + const pausedBeats = timeToBeats(state.playbackOffset); dom.playbackTime.textContent = `${state.playbackOffset.toFixed(2)}s (${pausedBeats.toFixed(2)}b)`; const indicatorX = pausedBeats * state.pixelsPerSecond; - dom.playbackIndicator.style.left = `${indicatorX}px`; dom.waveformPlaybackIndicator.style.left = `${indicatorX}px`; + dom.playbackIndicator.style.left = dom.waveformPlaybackIndicator.style.left = `${indicatorX}px`; if (wasPlaying) await startPlayback(); showMessage(`Seek to ${clickTime.toFixed(2)}s (${clickBeats.toFixed(2)}b)`, 'success'); } |
