summaryrefslogtreecommitdiff
path: root/tools/timeline_editor/index.html
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-12 13:29:25 +0100
committerskal <pascal.massimino@gmail.com>2026-02-12 13:29:25 +0100
commitb5a47693a4673a3bf2b6cb8a320718418ee09988 (patch)
tree722b9ff25ebc303ec39a4670008c7fb5b30b63f8 /tools/timeline_editor/index.html
parentcabef460cb4560e26b4e5f8bfaa97e8b71622c5a (diff)
Timeline editor: fix all position calculations when scrolled
Use container's getBoundingClientRect instead of timeline's. Timeline can scroll off-screen with negative left values. Container stays visible and provides reliable viewport coordinates. Fixes double-click seek and drag. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'tools/timeline_editor/index.html')
-rw-r--r--tools/timeline_editor/index.html20
1 files changed, 10 insertions, 10 deletions
diff --git a/tools/timeline_editor/index.html b/tools/timeline_editor/index.html
index 4ea93f2..eca7b97 100644
--- a/tools/timeline_editor/index.html
+++ b/tools/timeline_editor/index.html
@@ -624,9 +624,9 @@
function startDrag(e, type, seqIndex, effectIndex = null) {
state.isDragging = true;
state.dragMoved = false;
- const timelineRect = dom.timeline.getBoundingClientRect();
+ const containerRect = dom.timelineContent.getBoundingClientRect();
const currentLeft = parseFloat(e.currentTarget.style.left) || 0;
- state.dragOffset.x = e.clientX - timelineRect.left + dom.timelineContent.scrollLeft - currentLeft;
+ state.dragOffset.x = e.clientX - containerRect.left + dom.timelineContent.scrollLeft - currentLeft;
state.dragOffset.y = e.clientY - e.currentTarget.getBoundingClientRect().top;
state.selectedItem = { type, index: seqIndex, seqIndex, effectIndex };
document.addEventListener('mousemove', onDrag); document.addEventListener('mouseup', stopDrag);
@@ -635,8 +635,8 @@
function onDrag(e) {
if (!state.isDragging || !state.selectedItem) return;
state.dragMoved = true;
- const timelineRect = dom.timeline.getBoundingClientRect();
- let newTime = Math.max(0, (e.clientX - timelineRect.left + dom.timelineContent.scrollLeft - state.dragOffset.x) / state.pixelsPerSecond);
+ const containerRect = dom.timelineContent.getBoundingClientRect();
+ let newTime = Math.max(0, (e.clientX - containerRect.left + dom.timelineContent.scrollLeft - state.dragOffset.x) / state.pixelsPerSecond);
if (state.quantizeUnit > 0) newTime = Math.round(newTime * state.quantizeUnit) / state.quantizeUnit;
if (state.selectedItem.type === 'sequence') state.sequences[state.selectedItem.index].startTime = newTime;
else if (state.selectedItem.type === 'effect') {
@@ -659,8 +659,8 @@
e.preventDefault(); state.isDraggingHandle = true; state.handleType = type;
state.selectedItem = { type: 'effect', seqIndex, effectIndex, index: seqIndex };
const seq = state.sequences[seqIndex], effect = seq.effects[effectIndex];
- const timelineRect = dom.timeline.getBoundingClientRect();
- const mouseTimeBeats = (e.clientX - timelineRect.left + dom.timelineContent.scrollLeft) / state.pixelsPerSecond;
+ const containerRect = dom.timelineContent.getBoundingClientRect();
+ const mouseTimeBeats = (e.clientX - containerRect.left + dom.timelineContent.scrollLeft) / state.pixelsPerSecond;
const handleTimeBeats = seq.startTime + (type === 'left' ? effect.startTime : effect.endTime);
state.handleDragOffset = handleTimeBeats - mouseTimeBeats;
document.addEventListener('mousemove', onHandleDrag); document.addEventListener('mouseup', stopHandleDrag);
@@ -668,8 +668,8 @@
function onHandleDrag(e) {
if (!state.isDraggingHandle || !state.selectedItem) return;
- const timelineRect = dom.timeline.getBoundingClientRect();
- let newTime = (e.clientX - timelineRect.left + dom.timelineContent.scrollLeft) / state.pixelsPerSecond + state.handleDragOffset;
+ const containerRect = dom.timelineContent.getBoundingClientRect();
+ let newTime = (e.clientX - containerRect.left + dom.timelineContent.scrollLeft) / state.pixelsPerSecond + state.handleDragOffset;
newTime = Math.max(0, newTime);
if (state.quantizeUnit > 0) newTime = Math.round(newTime * state.quantizeUnit) / state.quantizeUnit;
const seq = state.sequences[state.selectedItem.seqIndex], effect = seq.effects[state.selectedItem.effectIndex];
@@ -916,8 +916,8 @@
dom.timeline.addEventListener('dblclick', async e => {
if (e.target !== dom.timeline) return;
- const timelineRect = dom.timeline.getBoundingClientRect();
- const clickX = e.clientX - timelineRect.left + dom.timelineContent.scrollLeft;
+ const containerRect = dom.timelineContent.getBoundingClientRect();
+ const clickX = e.clientX - containerRect.left + dom.timelineContent.scrollLeft;
const clickBeats = clickX / state.pixelsPerSecond;
const clickTime = beatsToTime(clickBeats);
if (state.audioBuffer) {