Spaces:
Sleeping
Sleeping
| import React, { useRef, useEffect } from 'react' | |
| function Waveform({ analyserData, isPlaying }) { | |
| const canvasRef = useRef(null) | |
| const animationRef = useRef(null) | |
| useEffect(() => { | |
| const canvas = canvasRef.current | |
| if (!canvas) return | |
| const ctx = canvas.getContext('2d') | |
| const dpr = window.devicePixelRatio || 1 | |
| // Set canvas size | |
| const rect = canvas.getBoundingClientRect() | |
| canvas.width = rect.width * dpr | |
| canvas.height = rect.height * dpr | |
| ctx.scale(dpr, dpr) | |
| const draw = () => { | |
| const width = rect.width | |
| const height = rect.height | |
| const data = analyserData || new Uint8Array(64).fill(0) | |
| // Clear canvas | |
| ctx.clearRect(0, 0, width, height) | |
| // Number of bars | |
| const barCount = 64 | |
| const barWidth = width / barCount - 2 | |
| const barGap = 2 | |
| // Create gradient | |
| const gradient = ctx.createLinearGradient(0, height, 0, 0) | |
| gradient.addColorStop(0, '#3b82f6') | |
| gradient.addColorStop(0.5, '#8b5cf6') | |
| gradient.addColorStop(1, '#a855f7') | |
| for (let i = 0; i < barCount; i++) { | |
| const value = data[i] || 0 | |
| const normalizedValue = value / 255 | |
| // Smooth decay when not playing | |
| const targetHeight = isPlaying ? normalizedValue * height * 0.9 : 0 | |
| const barHeight = Math.max(2, targetHeight) | |
| const x = i * (barWidth + barGap) | |
| const y = height - barHeight | |
| // Draw bar with rounded corners | |
| ctx.fillStyle = gradient | |
| ctx.beginPath() | |
| ctx.roundRect(x, y, barWidth, barHeight, 2) | |
| ctx.fill() | |
| // Add glow effect when playing | |
| if (isPlaying && normalizedValue > 0.5) { | |
| ctx.shadowColor = '#8b5cf6' | |
| ctx.shadowBlur = 10 | |
| ctx.fillStyle = gradient | |
| ctx.beginPath() | |
| ctx.roundRect(x, y, barWidth, barHeight, 2) | |
| ctx.fill() | |
| ctx.shadowBlur = 0 | |
| } | |
| } | |
| animationRef.current = requestAnimationFrame(draw) | |
| } | |
| draw() | |
| return () => { | |
| if (animationRef.current) { | |
| cancelAnimationFrame(animationRef.current) | |
| } | |
| } | |
| }, [analyserData, isPlaying]) | |
| return ( | |
| <div className="h-32 w-full"> | |
| <canvas | |
| ref={canvasRef} | |
| className="w-full h-full" | |
| style={{ display: 'block' }} | |
| /> | |
| </div> | |
| ) | |
| } | |
| export default Waveform | |