Files
sam-kd/ai_sam/ref/components/Visualizer.tsx
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

82 lines
2.2 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
interface VisualizerProps {
analyser: AnalyserNode | null;
active: boolean;
}
const Visualizer: React.FC<VisualizerProps> = ({ analyser, active }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
if (!canvasRef.current) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
if (!ctx) return;
let animationId: number;
const bufferLength = analyser ? analyser.frequencyBinCount : 0;
const dataArray = new Uint8Array(bufferLength);
const draw = () => {
animationId = requestAnimationFrame(draw);
const width = canvas.width;
const height = canvas.height;
ctx.clearRect(0, 0, width, height);
if (!active || !analyser) {
// Idle state: gentle pulse
const time = Date.now() / 1000;
ctx.beginPath();
ctx.arc(width / 2, height / 2, 20 + Math.sin(time * 2) * 2, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(99, 102, 241, 0.5)';
ctx.fill();
return;
}
analyser.getByteFrequencyData(dataArray);
const barWidth = (width / bufferLength) * 2.5;
let barHeight;
let x = 0;
// Draw mirrored spectrum from center
const centerX = width / 2;
for (let i = 0; i < bufferLength; i++) {
barHeight = dataArray[i] / 2;
// Gradient color
const gradient = ctx.createLinearGradient(0, height / 2 - barHeight, 0, height / 2 + barHeight);
gradient.addColorStop(0, '#818cf8'); // indigo-400
gradient.addColorStop(1, '#c084fc'); // purple-400
ctx.fillStyle = gradient;
// Right side
ctx.fillRect(centerX + x, height / 2 - barHeight / 2, barWidth, barHeight);
// Left side
ctx.fillRect(centerX - x - barWidth, height / 2 - barHeight / 2, barWidth, barHeight);
x += barWidth + 1;
}
};
draw();
return () => cancelAnimationFrame(animationId);
}, [analyser, active]);
return (
<canvas
ref={canvasRef}
width={300}
height={100}
className="w-full h-full"
/>
);
};
export default Visualizer;