54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
"use client";
|
|
import { motion } from "motion/react";
|
|
|
|
export function FloatingPaths({ position }: { position: number }) {
|
|
const paths = Array.from({ length: 36 }, (_, i) => ({
|
|
id: i,
|
|
d: `M-${380 - i * 5 * position} -${189 + i * 6}C-${
|
|
380 - i * 5 * position
|
|
} -${189 + i * 6} -${312 - i * 5 * position} ${216 - i * 6} ${
|
|
152 - i * 5 * position
|
|
} ${343 - i * 6}C${616 - i * 5 * position} ${470 - i * 6} ${
|
|
684 - i * 5 * position
|
|
} ${875 - i * 6} ${684 - i * 5 * position} ${875 - i * 6}`,
|
|
color: `rgba(15,23,42,${0.1 + i * 0.03})`,
|
|
width: 0.5 + i * 0.03,
|
|
}));
|
|
|
|
return (
|
|
<div className="pointer-events-none absolute inset-0">
|
|
<svg
|
|
className="h-full w-full text-primary"
|
|
fill="none"
|
|
viewBox="0 0 696 316"
|
|
>
|
|
<title>Background Paths</title>
|
|
{paths.map((path) => (
|
|
<motion.path
|
|
animate={{
|
|
pathLength: 1,
|
|
opacity: [0.3, 0.6, 0.3],
|
|
}}
|
|
d={path.d}
|
|
initial={{ pathLength: 0.3, opacity: 0.6 }}
|
|
key={path.id}
|
|
stroke="currentColor"
|
|
strokeOpacity={0.1 + path.id * 0.03}
|
|
strokeWidth={path.width}
|
|
transition={{
|
|
// Animating pathOffset forces a stroke-dasharray recompute on
|
|
// every frame for all 36 paths — opacity alone is far cheaper.
|
|
pathLength: { duration: 2, ease: "easeOut" },
|
|
opacity: {
|
|
duration: 20 + (path.id % 10),
|
|
repeat: Number.POSITIVE_INFINITY,
|
|
ease: "linear",
|
|
},
|
|
}}
|
|
/>
|
|
))}
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|