React-Anleitung
Inhaltsverzeichnis
- Installation
- Grundlegende Verwendung
- Konfetti-Effekt
- Feuerwerks-Effekt
- Schnee-Effekt
- Interaktive Verbindungen
- Themenwechsel
- ParticlesProvider
- Leistungsoptimierung
- Benutzerdefinierte Konfiguration
Installation
npm install @tsparticles/react tsparticlesOder mit Yarn:
yarn add @tsparticles/react tsparticles@tsparticles/react ist der offizielle React-Wrapper. Das Paket tsparticles ist die Kern-Engine.
Grundlegende Verwendung
Die einfachste Einrichtung: Rendern Sie die <Particles />-Komponente mit einem Optionsobjekt.
import { useCallback } from "react";
import Particles from "@tsparticles/react";
export default function App() {
const particlesLoaded = useCallback(async (container) => {
console.log("Partikel-Container geladen", container);
}, []);
const options = {
fpsLimit: 120,
particles: {
number: { value: 80 },
color: { value: "#00d4ff" },
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 2, max: 5 } },
move: {
enable: true,
speed: 2,
outModes: { default: "bounce" },
},
},
background: { color: "#0d1117" },
};
return <Particles id="tsparticles" particlesLoaded={particlesLoaded} options={options} />;
}Wichtig: Die <Particles />-Komponente erfordert, dass die Engine zuerst initialisiert wird. Verwenden Sie initParticlesEngine von @tsparticles/react oder den <ParticlesProvider>, um Ihre Presets vor dem Rendern der Komponente zu laden.
Konfetti-Effekt
Rendern Sie einen Konfetti-Ausbruch mit dem Konfetti-Preset.
import Particles from "@tsparticles/react";
export default function Confetti() {
const options = {
preset: "confetti",
fullScreen: { enable: true, zIndex: -1 },
confetti: {
colors: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff"],
particleCount: 150,
spread: 70,
origin: { x: 0.5, y: 0.5 },
},
};
return <Particles id="confetti" options={options} />;
}Stellen Sie sicher, dass Sie das Konfetti-Preset geladen haben:
npm install @tsparticles/preset-confettiDann registrieren Sie es in Ihrem App-Einstiegspunkt:
import { initParticlesEngine } from "@tsparticles/react";
import { loadConfettiPreset } from "@tsparticles/preset-confetti";
initParticlesEngine(async (engine) => {
await loadConfettiPreset(engine);
});Feuerwerks-Effekt
Ein Vollbild-Feuerwerk.
import { useCallback, useMemo } from "react";
import Particles from "@tsparticles/react";
export default function Fireworks() {
const particlesLoaded = useCallback(async (container) => {
console.log("Feuerwerk geladen", container);
}, []);
const options = useMemo(
() => ({
preset: "fireworks",
fullScreen: { enable: true, zIndex: -1 },
fireworks: {
background: "#000000",
brightness: 100,
colors: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", "#00ffff"],
intensity: 30,
life: { min: 4, max: 8 },
traces: 20,
explosion: { min: 30, max: 60 },
},
}),
[],
);
return <Particles id="fireworks" particlesLoaded={particlesLoaded} options={options} />;
}Installieren Sie das Preset:
npm install @tsparticles/preset-fireworksSchnee-Effekt
Sanft fallende Schneeflocken mit dem Schnee-Preset.
import { useCallback, useMemo } from "react";
import Particles from "@tsparticles/react";
export default function Snow() {
const particlesLoaded = useCallback(async (container) => {
console.log("Schnee geladen", container);
}, []);
const options = useMemo(
() => ({
preset: "snow",
fullScreen: { enable: true, zIndex: -1 },
snow: {
color: "#ffffff",
opacity: { min: 0.3, max: 0.9 },
size: { min: 1, max: 4 },
speed: { min: 0.5, max: 2 },
wobble: true,
},
}),
[],
);
return <Particles id="snow" particlesLoaded={particlesLoaded} options={options} />;
}Installieren Sie das Preset:
npm install @tsparticles/preset-snowInteraktive Verbindungen
Ein verbundenes Knoten-Netzwerk mit Maus-Hover-Grab und Klick-Push.
import { useCallback, useMemo } from "react";
import Particles from "@tsparticles/react";
export default function InteractiveLinks() {
const particlesLoaded = useCallback(async (container) => {
console.log("Interaktive Verbindungen geladen", container);
}, []);
const options = useMemo(
() => ({
fpsLimit: 60,
particles: {
number: { value: 80, density: { enable: true } },
color: { value: "#00d4ff" },
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 1, max: 4 } },
links: {
enable: true,
distance: 150,
color: "#00d4ff",
opacity: 0.4,
width: 1,
},
move: {
enable: true,
speed: 1.5,
outModes: { default: "bounce" },
},
},
interactivity: {
events: {
onHover: { enable: true, mode: "grab" },
onClick: { enable: true, mode: "push" },
},
modes: {
grab: { distance: 180, links: { opacity: 0.8 } },
push: { quantity: 4 },
},
},
background: { color: "#0d1117" },
}),
[],
);
return <Particles id="interactive-links" particlesLoaded={particlesLoaded} options={options} />;
}Themenwechsel
Definieren Sie mehrere Themes und wechseln Sie zwischen ihnen mit einem Klick.
import { useCallback, useMemo, useRef, useState } from "react";
import Particles from "@tsparticles/react";
export default function ThemeSwitcher() {
const containerRef = useRef(null);
const [currentTheme, setCurrentTheme] = useState("dark");
const particlesLoaded = useCallback(async (container) => {
containerRef.current = container;
}, []);
const options = useMemo(
() => ({
fpsLimit: 60,
particles: {
number: { value: 60 },
color: { value: "#00d4ff" },
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 2, max: 5 } },
links: { enable: true, distance: 150, color: "#00d4ff", opacity: 0.3 },
move: { enable: true, speed: 1.5, outModes: { default: "bounce" } },
},
background: { color: "#0d1117" },
themes: [
{
name: "dark",
default: { value: true },
options: {
background: { color: "#0d1117" },
particles: { color: { value: "#00d4ff" }, links: { color: "#00d4ff" } },
},
},
{
name: "light",
options: {
background: { color: "#f5f5f5" },
particles: { color: { value: "#e74c3c" }, links: { color: "#333333" } },
},
},
{
name: "forest",
options: {
background: { color: "#1a3a1a" },
particles: { color: { value: "#7ec850" }, links: { color: "#7ec850" } },
},
},
],
}),
[],
);
const switchTheme = useCallback((theme) => {
setCurrentTheme(theme);
if (containerRef.current) {
containerRef.current.loadTheme(theme);
}
}, []);
return (
<div style={{ position: "relative", width: "100%", height: "100vh" }}>
<Particles id="theme-switcher" particlesLoaded={particlesLoaded} options={options} />
<div
style={{
position: "absolute",
bottom: 20,
left: "50%",
transform: "translateX(-50%)",
zIndex: 10,
display: "flex",
gap: 8,
}}
>
<button onClick={() => switchTheme("dark")} style={btnStyle(currentTheme === "dark")}>
Dunkel
</button>
<button onClick={() => switchTheme("light")} style={btnStyle(currentTheme === "light")}>
Hell
</button>
<button onClick={() => switchTheme("forest")} style={btnStyle(currentTheme === "forest")}>
Wald
</button>
</div>
</div>
);
}
const btnStyle = (active) => ({
padding: "8px 16px",
border: "none",
borderRadius: 6,
background: active ? "#333" : "#666",
color: "#fff",
cursor: "pointer",
});ParticlesProvider
Verwenden Sie ParticlesProvider, um die Engine einmal im App-Root zu initialisieren. Dies ist der empfohlene Ansatz, wenn Sie mehrere Partikel-Komponenten haben oder benutzerdefinierte Presets verwenden.
// App.jsx
import { ParticlesProvider } from "@tsparticles/react";
import { loadSlim } from "@tsparticles/slim";
import Home from "./Home";
const engineInit = async (engine) => {
await loadSlim(engine);
// Zusätzliche Presets hier laden:
// await loadConfettiPreset(engine);
// await loadFireworksPreset(engine);
// await loadSnowPreset(engine);
};
export default function App() {
return (
<ParticlesProvider load={engineInit}>
<Home />
</ParticlesProvider>
);
}// Home.jsx
import Particles from "@tsparticles/react";
export default function Home() {
return (
<Particles
id="tsparticles"
options={{
particles: {
number: { value: 50 },
color: { value: "#ff6b6b" },
shape: { type: "circle" },
opacity: { value: 0.7 },
size: { value: { min: 2, max: 6 } },
move: { enable: true, speed: 1, outModes: { default: "bounce" } },
},
background: { color: "#1a1a2e" },
}}
/>
);
}Wenn Sie Ihren Baum mit ParticlesProvider umschließen, erbt jede untergeordnete <Particles />-Komponente dieselbe Engine-Instanz. Dies vermeidet die erneute Initialisierung der Engine bei jedem Mount.
Leistungsoptimierung
Memoisieren Sie immer Callbacks und Optionen, um unnötige Neu-Renderings zu verhindern.
import { useCallback, useMemo, useState } from "react";
import Particles from "@tsparticles/react";
export default function PerformanceExample() {
const [visible, setVisible] = useState(true);
// Callback memoieren — stabile Referenz über Renderings hinweg
const particlesLoaded = useCallback(async (container) => {
// Wird einmal pro Container-Mount aufgerufen
console.log("Container bereit", container?.id);
}, []);
// Optionsobjekt memoieren — wird nur bei Abhängigkeitsänderungen neu berechnet
const options = useMemo(
() => ({
fpsLimit: 60,
particles: {
number: { value: 100, density: { enable: true } },
color: { value: ["#ff6b6b", "#feca57", "#48dbfb"] },
shape: { type: "circle" },
opacity: { value: { min: 0.3, max: 0.7 } },
size: { value: { min: 2, max: 5 } },
links: {
enable: true,
distance: 120,
color: "random",
opacity: 0.3,
},
move: {
enable: true,
speed: 1,
outModes: { default: "bounce" },
},
},
background: { color: "#0d1117" },
}),
[],
);
// Canvas-Auflösung auf Geräten mit geringer Leistung reduzieren
const responsiveOptions = useMemo(
() => ({
...options,
detectRetina: window.devicePixelRatio <= 2,
fpsLimit: window.innerWidth < 768 ? 30 : 60,
}),
[options],
);
return (
<div>
<button onClick={() => setVisible((v) => !v)}>{visible ? "Ausblenden" : "Anzeigen"} Partikel</button>
{visible && <Particles id="perf-particles" particlesLoaded={particlesLoaded} options={responsiveOptions} />}
</div>
);
}Wichtige Tipps:
- Verwenden Sie immer
useMemofür dasoptions-Objekt. - Verwenden Sie immer
useCallbackfür denparticlesLoaded-Handler. - Senken Sie
fpsLimitauf mobilen Geräten. - Setzen Sie
detectRetina: falseauf Geräten mit >2x Pixelverhältnis, um die Canvas-Größe zu halbieren. - Montieren Sie
<Particles />bedingt ab, wenn es nicht im Viewport ist.
Reactive Behavior
The <Particles> component reacts to prop changes at runtime:
id,options, orurlchange → the existing container is destroyed and particles are reloaded with the new values.themechange →loadThemeis called on the existing container. This requires the optional@tsparticles/plugin-themespackage to be loaded (otherwise it is a safe no-op).
On component unmount, the particles container is automatically destroyed — no orphan animations remain.
Benutzerdefinierte Konfiguration
Ein vollständiges benutzerdefiniertes Beispiel, das mehrere Formen, Interaktivität, Themes und einen Farbverlaufshintergrund kombiniert.
import { useCallback, useMemo } from "react";
import Particles from "@tsparticles/react";
export default function CustomConfig() {
const particlesLoaded = useCallback(async (container) => {
console.log("Benutzerdefinierte Konfiguration geladen", container);
}, []);
const options = useMemo(
() => ({
fullScreen: { enable: true, zIndex: 0 },
fpsLimit: 60,
particles: {
number: { value: 60, density: { enable: true, width: 800, height: 800 } },
color: {
value: ["#ff6b6b", "#feca57", "#48dbfb", "#ff9ff3", "#54a0ff"],
},
shape: {
type: ["circle", "triangle", "polygon"],
options: {
polygon: { sides: 6 },
},
},
opacity: { value: { min: 0.4, max: 0.8 } },
size: { value: { min: 3, max: 8 } },
links: {
enable: true,
distance: 200,
color: "#ffffff",
opacity: 0.15,
width: 1,
},
move: {
enable: true,
speed: 2,
direction: "none",
random: true,
outModes: { default: "out" },
},
},
interactivity: {
events: {
onHover: { enable: true, mode: "attract" },
onClick: { enable: true, mode: "repulse" },
},
modes: {
attract: { distance: 200, duration: 0.4, factor: 1 },
repulse: { distance: 200, duration: 0.4 },
},
},
background: { color: "#0f0f23" },
themes: [
{
name: "light",
default: { value: false },
options: {
background: { color: "#f0f0f5" },
particles: {
color: { value: ["#e74c3c", "#2ecc71", "#3498db", "#f1c40f"] },
links: { color: "#333333", opacity: 0.2 },
opacity: { value: { min: 0.5, max: 0.9 } },
},
},
},
],
}),
[],
);
return <Particles id="custom-config" particlesLoaded={particlesLoaded} options={options} />;
}Sie haben jetzt die Kernmuster für die Verwendung von tsParticles in React kennengelernt. Jedes Beispiel ist in sich geschlossen und kann direkt in eine Komponentendatei übernommen werden.
