From 70039c5154f66463e2a3895223a3ec3f99eebc38 Mon Sep 17 00:00:00 2001 From: Lee-Orr Date: Tue, 12 Mar 2024 13:59:40 -0400 Subject: [PATCH] basic pan & zoom --- .../src/app/anim-timeline.element.ts | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/studio-frontend/src/app/anim-timeline.element.ts b/studio-frontend/src/app/anim-timeline.element.ts index 59cd97e..89b67ab 100644 --- a/studio-frontend/src/app/anim-timeline.element.ts +++ b/studio-frontend/src/app/anim-timeline.element.ts @@ -69,11 +69,6 @@ export class AnimTimelineElement extends LitElement { /** The width (in px) of the timeline view */ @state() _renderWidth!: number; - /** The offset from 0seconds of the left edge of the timeline view, in px */ - @state() _offsetX = 0; - /** The vertical scroll offset (in px) */ - @state() _offsetY = 0; - /** * `true` when the timeline is being mouse-panned. Primarily useful for * setting the cursor style to the grabby hand. @@ -120,7 +115,7 @@ export class AnimTimelineElement extends LitElement { event.stopImmediatePropagation(); if (event.ctrlKey) { - this.#zoomTimeline(event.offsetX, event.deltaY); + this.#zoomTimeline(event.clientX, event.deltaY); } else if (event.deltaX) { this.#pan(-event.deltaX); } else if (event.shiftKey && event.deltaY) { @@ -149,17 +144,13 @@ export class AnimTimelineElement extends LitElement { #zoomTimeline(origin: number, delta: number): void { const currentRange = this.rangeEnd - this.rangeStart; - const deltaRange = delta * 4; + const elementRect = this.getBoundingClientRect(); + const focusPoint = (origin - elementRect.x) / elementRect.width; - // FIXME: When zooming the timeline, the transform origin should be - // centered on the mouse cursor. Currently this does not work as - // intended, always centering on the 00:00 timestamp instead. - const t = ((this._offsetX + origin) * this.secondsPerPx.get()) / currentRange; - console.log(`t: ${t}`); - console.log(`deltaStart: ${-deltaRange * t}`); - console.log(`deltaEnd: ${deltaRange * (1 - t)}`); - const rangeStart = this.rangeStart - deltaRange * t; - const rangeEnd = this.rangeEnd + deltaRange * (1 - t); + const deltaTimeScale = delta * 0.001 * currentRange; + + const rangeStart = this.rangeStart - deltaTimeScale * focusPoint; + const rangeEnd = this.rangeEnd + deltaTimeScale * (1 - focusPoint); this.dispatchEvent(new CustomEvent("rangeStart-change", { detail: rangeStart })); this.dispatchEvent(new CustomEvent("rangeEnd-change", { detail: rangeEnd })); @@ -178,11 +169,11 @@ export class AnimTimelineElement extends LitElement { } #pan(deltaPx: number): void { - this._offsetX += deltaPx; + const deltaChange = deltaPx * 0.001; + const scaledChange = (this.rangeEnd - this.rangeStart) * deltaChange; - const pxPerSecond = this.secondsPerPx.get(); - const rangeStart = this.rangeStart - deltaPx * pxPerSecond; - const rangeEnd = this.rangeEnd - deltaPx * pxPerSecond; + const rangeStart = this.rangeStart - scaledChange; + const rangeEnd = this.rangeEnd - scaledChange; this.dispatchEvent(new CustomEvent("rangeStart-change", { detail: rangeStart })); this.dispatchEvent(new CustomEvent("rangeEnd-change", { detail: rangeEnd })); @@ -242,13 +233,6 @@ export class AnimTimelineElement extends LitElement { }`; } - /** - * Convert a time value (in seconds) to a px offset from the left edge of the view - */ - secondsToPx(seconds: number): number { - return this._offsetX + seconds * this.secondsPerPx.get(); - } - protected override render() { const { subdivision: subdivisionScale, @@ -262,7 +246,7 @@ export class AnimTimelineElement extends LitElement { const scaledEnd = this.rangeEnd / subdivisionScale; const range = this.rangeEnd - this.rangeStart; - console.log("Scaled Start", scaledStart, "Scaled End", scaledEnd, "Range", range); + console.log("Scaled Start", scaledStart, "Scaled End", scaledEnd, "Range Start", this.rangeStart, "Range End", this.rangeEnd, "Range", range, "Playhead", this.playHead); let subdivisions : Array<{seconds: number, fraction: number, isMajor: boolean}> = []; let currentOffset = scaledStart; @@ -271,7 +255,7 @@ export class AnimTimelineElement extends LitElement { while (currentOffset < scaledEnd) { const currentSeconds = currentOffsetSeconds; const isMajor = currentOffsetSeconds % majorSubdivisionScale === 0; - subdivisions.push({ seconds: currentSeconds, fraction: currentSeconds / range, isMajor }); + subdivisions.push({ seconds: currentSeconds, fraction: (currentSeconds - this.rangeStart) / range, isMajor }); let nextSubdiv = Math.ceil(currentOffset); if (Math.abs(nextSubdiv - currentOffset) < 0.1) { nextSubdiv += 1; @@ -349,7 +333,7 @@ export class AnimTimelineElement extends LitElement { selected: this._selectedKeyframe === id, })} style=${styleMap({ - left: `${this.secondsToPx(keyframe)}px` + left: `${100 * (keyframe - this.rangeStart) / range}%` })} tabindex="-1" ${drag({