jam-tracks / frontend /src /components /Waveform.jsx
Mina Emadi
updated the MVP-Initial upload
a0fcd39
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