fix: timeline zoom and waveform rendering improvements
- Fix timeline width calculation to always fill viewport at minimum - Fix waveform sampling to match timeline width calculation exactly - Fix infinite scroll loop by removing circular callback - Ensure scrollbars appear correctly when zooming in - Use consistent PIXELS_PER_SECOND_BASE = 5 across all components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -42,10 +42,16 @@ export function TimeScale({
|
||||
|
||||
// Calculate total timeline width (match waveform calculation)
|
||||
// Uses 5 pixels per second as base scale, multiplied by zoom
|
||||
// Always ensure minimum width is at least viewport width for full coverage
|
||||
const PIXELS_PER_SECOND_BASE = 5;
|
||||
const totalWidth = React.useMemo(() => {
|
||||
return duration * zoom * PIXELS_PER_SECOND_BASE;
|
||||
}, [duration, zoom]);
|
||||
if (zoom >= 1) {
|
||||
const calculatedWidth = duration * zoom * PIXELS_PER_SECOND_BASE;
|
||||
// Ensure it's at least viewport width so timeline always fills
|
||||
return Math.max(calculatedWidth, viewportWidth);
|
||||
}
|
||||
return viewportWidth;
|
||||
}, [duration, zoom, viewportWidth]);
|
||||
|
||||
// Update viewport width on resize
|
||||
React.useEffect(() => {
|
||||
|
||||
@@ -329,7 +329,17 @@ export function Track({
|
||||
|
||||
const buffer = track.audioBuffer;
|
||||
const channelData = buffer.getChannelData(0);
|
||||
const samplesPerPixel = Math.floor(buffer.length / (width * zoom));
|
||||
// Calculate samples per pixel based on the total width
|
||||
// Must match the timeline calculation exactly
|
||||
const PIXELS_PER_SECOND_BASE = 5;
|
||||
let totalWidth;
|
||||
if (zoom >= 1) {
|
||||
const calculatedWidth = duration * zoom * PIXELS_PER_SECOND_BASE;
|
||||
totalWidth = Math.max(calculatedWidth, width);
|
||||
} else {
|
||||
totalWidth = width;
|
||||
}
|
||||
const samplesPerPixel = buffer.length / totalWidth;
|
||||
|
||||
// Draw waveform
|
||||
ctx.fillStyle = track.color;
|
||||
|
||||
@@ -170,12 +170,7 @@ export function TrackList({
|
||||
});
|
||||
|
||||
setSyncingScroll(false);
|
||||
|
||||
// Also call the external callback if provided
|
||||
if (onTimeScaleScroll) {
|
||||
onTimeScaleScroll();
|
||||
}
|
||||
}, [syncingScroll, onTimeScaleScroll]);
|
||||
}, [syncingScroll]);
|
||||
|
||||
// Expose the scroll handler via ref so AudioEditor can call it
|
||||
React.useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user