From 34681821e448922f8f5616e22502a66e5f67fec2 Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Mon, 13 Dec 2021 05:10:07 +0100 Subject: [PATCH] Improve waveform selection behaviour --- frontend/src/App.tsx | 10 ++++----- frontend/src/Waveform.tsx | 44 ++++++++++++--------------------------- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index eadf263..5336833 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -210,26 +210,26 @@ function App(): JSX.Element { setPositionFromFrame(newViewport.start); }, - [mediaSet, audio, video] + [mediaSet, audio, video, selection] ); // handler called when the selection in the main waveform view is changed. const handleWaveformSelectionChange = useCallback( - (selection: Frames) => { - setSelection(selection); + (newSelection: Frames) => { + setSelection(newSelection); if (mediaSet == null) { return; } // move playback position to start of selection - const ratio = selection.start / mediaSet.audioFrames; + const ratio = newSelection.start / mediaSet.audioFrames; const currentTime = (mediaSet.audioFrames / mediaSet.audioSampleRate) * ratio; audio.currentTime = currentTime; video.currentTime = currentTime; }, - [mediaSet, audio, video] + [mediaSet, audio, video, selection] ); const handlePlay = useCallback(() => { diff --git a/frontend/src/Waveform.tsx b/frontend/src/Waveform.tsx index fae374d..787419c 100644 --- a/frontend/src/Waveform.tsx +++ b/frontend/src/Waveform.tsx @@ -71,30 +71,20 @@ export const Waveform: React.FC = ({ setPositionPixels(null); return; } - const logicalPixelsPerFrame = - CanvasLogicalWidth / (viewport.end - viewport.start); - const positionPixels = (frame - viewport.start) * logicalPixelsPerFrame; + const pixelsPerFrame = CanvasLogicalWidth / (viewport.end - viewport.start); + const positionPixels = (frame - viewport.start) * pixelsPerFrame; setPositionPixels(positionPixels); }, [mediaSet, position, viewport]); // update selectedPixels on viewport change useEffect(() => { - const start = frameToCanvasX(selectedFrames.start); - const end = frameToCanvasX(selectedFrames.end); - - // more verbose than it has to be to make TypeScript happy - if (start == null && end == null) { - setSelectedPixels({ start: 0, end: 0 }); - } else if (start == null && end != null) { - setSelectedPixels({ start: 0, end: end }); - } else if (start != null && end == null) { - setSelectedPixels({ start: 0, end: CanvasLogicalWidth }); - } else if (start != null && end != null) { - setSelectedPixels({ start, end }); - } else { - console.error('unreachable'); - } - }, [viewport]); + const start = Math.max(frameToCanvasX(selectedFrames.start), 0); + const end = Math.min( + frameToCanvasX(selectedFrames.end), + CanvasLogicalWidth + ); + setSelectedPixels({ start, end }); + }, [viewport, selectedFrames]); // handlers @@ -112,26 +102,18 @@ export const Waveform: React.FC = ({ setSelectedFrames(selectedFrames); onSelectionChange(selectedFrames); }, - [viewport] + [viewport, selectedFrames] ); // helpers const frameToCanvasX = useCallback( - (frame: number): number | null => { - if (mediaSet == null) { - return null; - } - - if (frame < viewport.start || frame > viewport.end) { - return null; - } - + (frame: number): number => { const pixelsPerFrame = CanvasLogicalWidth / (viewport.end - viewport.start); - return (frame - viewport.start) * pixelsPerFrame; + return Math.round((frame - viewport.start) * pixelsPerFrame); }, - [mediaSet, viewport] + [viewport] ); // render component