Files

6.8 KiB

Here is the translation of the document into English Markdown format:

Geometric Analysis: Progressive Center Drift During Asymmetrical Zoom & Pre-Roll Gutter Solution

This document analyzes the mathematical root cause of center drift during zoom operations at asymmetric timeline markers (e.g., zooming at 1\text{ s} drifts drastically compared to 5\text{ s} on a 10\text{ s} total track length). It also provides a structural solution using boundary margins (Pre-roll/Post-roll Gutter) to lock the absolute anchor point in all interaction scenarios.


1. Mathematical Proof: Why Zooming at 1\text{ s} Drifts Further Than 5\text{ s}

This visual discrepancy is not caused by random calculation precision errors, but is the mathematical result of boundary clamping (Scroll Left Clamping).

1.1. Conservation Equation for Mouse/Playhead Anchor Points

To preserve the visual location of time marker t at pixel coordinate X_{\text{viewport}} relative to the display before and after changing the zoom scale factor (Z_{\text{current}} \rightarrow Z_{\text{new}}), the required horizontal scroll offset S_{\text{new}} (scrollLeft) must satisfy:

S_{\text{new}} = (t \times Z_{\text{new}}) - X_{\text{viewport}}

1.2. Scenario Analysis: Zooming Out at X_{\text{viewport}} = 300\text{ px} (Cursor at Screen Center)

Assume the timeline is zoomed out significantly, reducing the zoom ratio down to Z_{\text{new}} = 100\text{ px/second}.

Scenario A: Operator zooms at the central symmetrical coordinate t = 5.0\text{ s}

Applying the target scroll position calculation:

S_{\text{new}} = (5.0 \times 100) - 300 = 500 - 300 = +200\text{ px}
  • Result: Because +200\text{ px} \ge 0, the scroll position resides safely within physical boundary limits. The browser sets scrollLeft = 200 smoothly. The 5.0\text{ s} point remains locked at position 300\text{ px} on the screen with a spatial drift of 0\text{ px}.

Scenario B: Operator zooms at an asymmetrical coordinate near the left edge t = 1.0\text{ s}

Applying the target scroll position calculation:

S_{\text{new}} = (1.0 \times 100) - 300 = 100 - 300 = -200\text{ px}
  • Critical Issue: Browsers and operating hardware cannot execute negative scroll values (scrollLeft < 0), instantly clamping the horizontal scroll position at the minimum boundary $S_{\text{clamped}} = 0\text{ px}$.
  • Due to this clamping, the actual on-screen rendering coordinate of the 1.0\text{ s} milestone drifts to:
X_{\text{viewport\_actual}} = (1.0 \times 100) - 0 = 100\text{ px}
  • Visual Discrepancy: The 1.0\text{ s} marker, which should remain stationary at coordinate 300\text{ px}, is pulled to the left to coordinate $100\text{ px}$ (resulting in a spatial shift of 200\text{ px}).

Geometric Principle: The smaller the zoom anchor timestamp t (the closer it sits to the left boundary), the more likely the required scroll position S_{\text{new}} drops below zero to be clamped at 0, increasing visual waveform displacement during zoom-out operations.


2. Professional DAW Solution: Pre-Roll & Post-Roll Gutters

To permanently eliminate this behavior and give SonicForge Studio a professional zoom experience similar to Reaper or Adobe Audition, apply a Pre-roll & Post-roll Gutter (Boundary Margins).

|<─────────────────── Actual Timeline Scroll Width ───────────────────>|
+──────────────────────────┬───────────────────────────────────────────+
| [ Pre-roll Gutter ]      │ 0:00.000 (Actual music start time)        |
| (Width: W_viewport)      │                                           |
| (scrollLeft can run here)│  [ Waveform and track grid start here... ]|
+──────────────────────────┴───────────────────────────────────────────+
▲
│ [ 1.0s anchor point remains 100% stationary here ]
│ Because the scrollbar is allowed to retreat negatively into the gutter!

  1. Enabling Visual Negative Scrolling: Instead of starting the timeline canvas at pixel coordinate 0\text{ px} (corresponding to 0.0\text{ s}), prepend an empty padding region (Gutter) equal to the full viewport width W_{\text{viewport}} (e.g., 1200\text{ px}) before the 0.0\text{ s} mark.
  2. Updated Coordinate Mapping Formula: The physical pixel coordinate X of timestamp t on the Canvas includes the offset padding:
X_t = (t \times Z) + W_{\text{pre\_roll}}
  1. Unclamped Scroll Conservation Equation: When zooming at any asymmetrical timestamp (including 0.1\text{ s} or 0.0\text{ s}):
S_{\text{new}} = (t \times Z_{\text{new}}) + W_{\text{pre\_roll}} - X_{\text{viewport}}
  • Because W_{\text{pre\_roll}} is added, S_{\text{new}} remains greater than 0 during standard zoom-out actions, eliminating the clamp at 0. Your 1.0\text{ s} timestamp or playhead stays stationary, the waveform graphics scale symmetrically, and the 0.0\text{ s} mark smoothly recedes toward the center of the viewport, exposing a subtle, professional dark gray pre-roll gutter area in front of the track.

3. Implementing the Boundary Lock Algorithm in Source Code

Below is the upgraded mouse wheel zoom event handler for index.html, incorporating pre-roll margin compensation:

const handleTimelineZoomWithGutter = (e) => {
    if (!e.ctrlKey) return; 
    e.preventDefault();

    const timelineWrapper = timelineWrapperRef.current;
    if (!timelineWrapper) return;

    const rect = timelineWrapper.getBoundingClientRect();
    const mouseXInViewport = e.clientX - rect.left;
    
    // Pre-roll gutter padding equal to half the viewport width to allow scrolling past 0s
    const preRollPadding = rect.width / 2;

    const scrollLeftCurrent = timelineWrapper.scrollLeft;
    const zoomCurrent = zoom;
    const anchorTime = (scrollLeftCurrent + mouseXInViewport - preRollPadding) / zoomCurrent;

    const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
    let zoomNew = zoomCurrent * zoomFactor;
    
    // Apply zoom constraints
    zoomNew = Math.max(minZoom, Math.min(2000, zoomNew));

    // Calculate new scroll offset preserving the anchor point under the cursor
    const scrollLeftNew = (anchorTime * zoomNew) + preRollPadding - mouseXInViewport;

    // Update state
    setZoom(zoomNew);
    
    requestAnimationFrame(() => {
        timelineWrapper.scrollLeft = scrollLeftNew;
    });
};

This upgrade enables SonicForge Studio to achieve zero-latency, sample-accurate zooming with studio-grade anchor locking!