113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useEffect } from "react";
|
|
|
|
interface SectionDividerProps {
|
|
variant?: "gradient" | "pulse" | "waveform";
|
|
className?: string;
|
|
}
|
|
|
|
export default function SectionDivider({
|
|
variant = "gradient",
|
|
className = "",
|
|
}: SectionDividerProps) {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (variant !== "waveform") return;
|
|
const canvas = canvasRef.current;
|
|
if (!canvas) return;
|
|
|
|
const ctx = canvas.getContext("2d");
|
|
if (!ctx) return;
|
|
|
|
let animId: number;
|
|
|
|
const resize = () => {
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = 60;
|
|
};
|
|
resize();
|
|
window.addEventListener("resize", resize);
|
|
|
|
const render = () => {
|
|
animId = requestAnimationFrame(render);
|
|
const { width, height } = canvas;
|
|
const t = performance.now() * 0.001;
|
|
|
|
ctx.clearRect(0, 0, width, height);
|
|
|
|
// Draw multiple waveforms
|
|
for (let wave = 0; wave < 3; wave++) {
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = `rgba(204, 255, 0, ${0.1 - wave * 0.03})`;
|
|
ctx.lineWidth = 1;
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
const frequency = 0.005 + wave * 0.002;
|
|
const amplitude = 8 + wave * 4;
|
|
const speed = t * (0.5 + wave * 0.2);
|
|
const y =
|
|
height / 2 +
|
|
Math.sin(x * frequency + speed) * amplitude +
|
|
Math.sin(x * frequency * 2.3 + speed * 1.5) * (amplitude * 0.4);
|
|
|
|
if (x === 0) ctx.moveTo(x, y);
|
|
else ctx.lineTo(x, y);
|
|
}
|
|
|
|
ctx.stroke();
|
|
}
|
|
};
|
|
|
|
animId = requestAnimationFrame(render);
|
|
|
|
return () => {
|
|
cancelAnimationFrame(animId);
|
|
window.removeEventListener("resize", resize);
|
|
};
|
|
}, [variant]);
|
|
|
|
if (variant === "gradient") {
|
|
return (
|
|
<div className={`relative h-px w-full overflow-hidden ${className}`}>
|
|
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-[var(--slash)] to-transparent opacity-30" />
|
|
<div
|
|
className="absolute inset-0 bg-gradient-to-r from-transparent via-[var(--slash)] to-transparent opacity-60"
|
|
style={{
|
|
animation: "shimmerDivider 3s ease-in-out infinite",
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (variant === "pulse") {
|
|
return (
|
|
<div className={`flex items-center justify-center gap-2 py-8 ${className}`}>
|
|
{[...Array(5)].map((_, i) => (
|
|
<div
|
|
key={i}
|
|
className="h-1 w-1 rounded-full bg-[var(--slash)]"
|
|
style={{
|
|
animation: `pulseDot 2s ease-in-out ${i * 0.15}s infinite`,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// waveform
|
|
return (
|
|
<div className={`relative ${className}`}>
|
|
<canvas
|
|
ref={canvasRef}
|
|
className="w-full opacity-60"
|
|
style={{ height: 60 }}
|
|
aria-hidden="true"
|
|
/>
|
|
</div>
|
|
);
|
|
}
|