import { useEffect, useState, useRef } from 'react'; import { Frames, MediaSet } from './App'; import { WaveformCanvas } from './WaveformCanvas'; import { secsToCanvasX } from './Helpers'; interface Props { mediaSet: MediaSet; position: number; viewport: Frames; offsetPixels: number; } export const CanvasLogicalWidth = 2000; export const CanvasLogicalHeight = 500; export const Waveform: React.FC = ({ mediaSet, position, viewport, offsetPixels, }: Props) => { const [peaks, setPeaks] = useState([[], []]); const hudCanvasRef = useRef(null); // effects // load peaks on MediaSet change useEffect(() => { (async function () { if (mediaSet == null) { return; } let endFrame = viewport.end; if (endFrame <= viewport.start) { endFrame = mediaSet.audio.frames; } const resp = await fetch( `http://localhost:8888/api/media_sets/${mediaSet.id}/peaks?start=${viewport.start}&end=${endFrame}&bins=${CanvasLogicalWidth}` ); const newPeaks = await resp.json(); setPeaks(newPeaks); })(); }, [mediaSet, viewport]); // render HUD useEffect(() => { const canvas = hudCanvasRef.current; if (canvas == null) { return; } const ctx = canvas.getContext('2d'); if (ctx == null) { console.error('no hud 2d context available'); return; } ctx.clearRect(0, 0, canvas.width, canvas.height); if (mediaSet == null) { return; } const x = secsToCanvasX(position, mediaSet.audio.sampleRate, viewport); if (x == null) { return; } ctx.strokeStyle = 'red'; ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineWidth = 4; ctx.lineTo(x, canvas.height); ctx.stroke(); }, [viewport, position]); // render component const containerStyles = { background: 'black', margin: '0 ' + offsetPixels + 'px', flexGrow: 1, position: 'relative', } as React.CSSProperties; const canvasStyles = { position: 'absolute', width: '100%', height: '100%', display: 'block', } as React.CSSProperties; return ( <>
); };