Files

6.6 KiB

Technical Specification: Minimum Zoom Constraint Specification

This document defines the algorithm and graphical rendering mechanics (Rendering Logic) to solve the following problem: When zooming out to the absolute minimum, the audio waveforms of all tracks must fit perfectly within the horizontal width of the Editor viewport, as realistically illustrated in image_f0c1e0.png.


1. Current State & Design Problem Analysis

Based on image_f0c1e0.png, when a user performs a zoom-out operation to the absolute minimum limit:

  • Visual Requirement: The entire audio range from the starting point (0.00\text{ s}) to the termination point (T_{\text{max}}) must be captured completely within the "Display Width" (W_{\text{viewport}}) of the screen.
  • Desired Outcomes:
  • No redundant horizontal scrollbars appear underneath the timeline.
  • No massive black voids (dead space) exist on the right side if the track duration is shorter than the viewport bounding container.
  • All audio tracks are scaled down synchronously in physical size to fully display their respective waveforms from start to finish.
                      Editor Viewport Width (W_viewport)
|<───────────────────────────────────────────────────────────────────────────────────>|
+─────────────────────────────────────────────────────────────────────────────────────+
| Ruler: 0:00        0:10        0:20        0:30        0:40        0:50        1:00     |
+─────────────────────────────────────────────────────────────────────────────────────+
| Track 1: [███████████████████████████████████████████████████████████████████████]  |
|                                                                                     |
| Track 2: [███████████████████████████████████████████████████████████████████████]  |
+─────────────────────────────────────────────────────────────────────────────────────+


2. Dynamic Min-Zoom Calculation Algorithm

To guarantee that the waveforms always fit perfectly even when the user resizes the browser window (or a Python application window), the minimum boundary zoom value (Z_{\text{min}}) must be evaluated dynamically.

Let:

  • W_{\text{viewport}} (pixels): The actual horizontal visible width of the timeline container viewport.
  • T_{\text{max}} (seconds): The maximum duration among all active tracks residing on the timeline.
  • Z (pixels/second): The current zoom scale factor (Zoom Level—the number of physical pixels representing 1 second of audio).

The bounding minimum zoom level (Z_{\text{min}}) is determined by the formula:

Z_{\text{min}} = \frac{W_{\text{viewport}}}{T_{\text{max}}}

2.1. Zoom Level Constraints

Throughout mouse wheel interaction events triggered to adjust Z, the system must check bounds and strictly clamp the value within a safe operating spectrum:

Z_{\text{clipped}} = \text{clamp}(Z_{\text{min}}, Z_{\text{target}}, Z_{\text{max}})

Where:

  • Z_{\text{max}}: The upper zoom-in boundary limit (e.g., fixed at 2000\text{ pixels/s} to eliminate canvas rendering memory overflow vulnerabilities).
  • Z_{\text{min}}: The dynamic lower zoom-out boundary limit (re-calculated based on fluctuations of W_{\text{viewport}} and T_{\text{max}}).

3. Synchronized Implementation Manual (Frontend JS & Python Porting)

3.1. Client-side Integration (JavaScript / React)

Utilize a ResizeObserver to systematically recompute Z_{\text{min}} as soon as the user scales the browser viewport:

// Initialize element targeting for the Timeline container frame
const timelineWrapper = document.getElementById('timeline-wrapper');

const resizeObserver = new ResizeObserver(entries => {
    for (let entry of entries) {
        const viewportWidth = entry.contentRect.width;
        
        // Compute dynamic Z_min boundary condition
        const computedMinZoom = viewportWidth / maxDuration;
        
        // Update state and instantly clamp current zoom so it doesn't fall below Z_min
        setZoom(prevZoom => {
            const nextZoom = Math.max(computedMinZoom, prevZoom);
            return nextZoom;
        });
    }
});
resizeObserver.observe(timelineWrapper);

3.2. Server-side / Desktop App Integration (Python PyQt6 / PySide6)

When porting this layout system and mathematical constraint model to a Python desktop application context, hook into the resizeEvent method of the QWidget class to handle container adjustments:

from PyQt6.QtWidgets import QWidget
from PyQt6.QtCore import QSize

class TimelineContainerWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.max_duration_seconds = 60.0  # Track duration benchmark (seconds)
        self.current_zoom = 100.0         # Current scale metric (pixels/second)
        self.max_zoom = 2000.0            # Strict upper ceiling for zoom-in operations

    def resizeEvent(self, event):
        """
        Intercepts the window/widget resizing event to refresh the minimum zoom bounds.
        """
        viewport_width = self.width()
        
        # 1. Evaluate the dynamic Z_min constraint from the new physical container width
        min_zoom = float(viewport_width) / self.max_duration_seconds
        
        # 2. Hard clamp the active zoom level to prevent dropping underneath min_zoom
        if self.current_zoom < min_zoom:
            self.current_zoom = min_zoom
            
        # 3. Request a graphical redraw of the waveform lanes
        self.update_waveform_painter()
        super().resizeEvent(event)

    def update_waveform_painter(self):
        # Triggers the QPainter paintEvent routine redraw execution block
        self.update()