56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Particles, { initParticlesEngine } from "@tsparticles/react";
|
|
import { loadSlim } from "@tsparticles/slim";
|
|
import type { ISourceOptions } from "@tsparticles/engine";
|
|
|
|
export function ParticleBackground() {
|
|
const [init, setInit] = useState(false);
|
|
|
|
useEffect(() => {
|
|
initParticlesEngine(async (engine) => {
|
|
await loadSlim(engine);
|
|
}).then(() => setInit(true));
|
|
}, []);
|
|
|
|
const options: ISourceOptions = {
|
|
background: { color: { value: "transparent" } },
|
|
fpsLimit: 60,
|
|
interactivity: {
|
|
events: { onHover: { enable: true, mode: "grab" } },
|
|
modes: { grab: { distance: 140, links: { opacity: 0.3 } } },
|
|
},
|
|
particles: {
|
|
color: { value: "#f59e0b" },
|
|
links: {
|
|
color: "#f59e0b",
|
|
distance: 120,
|
|
enable: true,
|
|
opacity: 0.15,
|
|
width: 0.5,
|
|
},
|
|
move: {
|
|
enable: true,
|
|
outModes: { default: "bounce" },
|
|
speed: 0.3,
|
|
},
|
|
number: { density: { enable: true, area: 800 }, value: 50 },
|
|
opacity: { value: { min: 0.1, max: 0.4 } },
|
|
shape: { type: "circle" },
|
|
size: { value: { min: 0.5, max: 2 } },
|
|
},
|
|
detectRetina: true,
|
|
};
|
|
|
|
if (!init) return null;
|
|
|
|
return (
|
|
<Particles
|
|
id="hero-particles"
|
|
className="pointer-events-none absolute inset-0"
|
|
options={options}
|
|
/>
|
|
);
|
|
}
|