Intégration Svelte
Le package @tsparticles/svelte fournit un composant Svelte natif pour tsParticles. Ce guide couvre Svelte (avec Vite) et SvelteKit, incluant les options réactives, la gestion des événements et les instances multiples.
Installation
npm install @tsparticles/svelte @tsparticles/enginePour le bundle complet ou les préréglages :
npm install tsparticles
npm install @tsparticles/preset-snow
npm install @tsparticles/preset-stars
npm install @tsparticles/preset-confetti
npm install @tsparticles/preset-fireworksUtilisation de base
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
let engineInitialised = false;
const particlesInit = async (engine: Engine): Promise<void> => {
await loadFull(engine);
engineInitialised = true;
};
const options: ISourceOptions = {
background: {
color: "#0d47a1",
},
fpsLimit: 120,
particles: {
number: {
value: 80,
},
color: {
value: "#ffffff",
},
shape: {
type: "circle",
},
opacity: {
value: 0.5,
},
size: {
value: { min: 1, max: 5 },
},
links: {
enable: true,
distance: 150,
color: "#ffffff",
opacity: 0.4,
width: 1,
},
move: {
enable: true,
speed: 2,
outModes: "out",
},
},
};
</script>
<Particles
id="tsparticles"
options={options}
on:init={particlesInit}
/>Initialisation du moteur
Passez un gestionnaire d'événement on:init pour charger les plugins et préréglages dont votre application a besoin :
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Engine } from "@tsparticles/engine";
const handleInit = async (event: CustomEvent<Engine>) => {
const engine = event.detail;
await loadFull(engine);
};
</script>
<Particles
id="tsparticles"
options={options}
on:init={handleInit}
/>Alternativement, utilisez l'utilitaire initParticlesEngine avant le montage :
<script lang="ts">
import Particles, { initParticlesEngine } from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import { onMount } from "svelte";
let ready = false;
onMount(async () => {
await initParticlesEngine(async (engine) => {
await loadFull(engine);
});
ready = true;
});
</script>
{#if ready}
<Particles id="tsparticles" options={options} />
{/if}Effet Neige
npm install @tsparticles/preset-snow<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadSnowPreset } from "@tsparticles/preset-snow";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
const handleInit = async (event: CustomEvent<Engine>) => {
await loadSnowPreset(event.detail);
};
const options: ISourceOptions = {
preset: "snow",
background: {
color: "#1a1a2e",
},
};
</script>
<Particles
id="snow"
{options}
on:init={handleInit}
/>Personnalisez le comportement du préréglage en fusionnant des options supplémentaires :
<script lang="ts">
const options: ISourceOptions = {
preset: "snow",
background: { color: "#0f0f23" },
particles: {
move: {
speed: 1.5, // chute de neige plus lente
},
opacity: {
value: 0.8, // flocons plus visibles
},
},
};
</script>Effet Étoiles
npm install @tsparticles/preset-stars<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadStarsPreset } from "@tsparticles/preset-stars";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
const handleInit = async (event: CustomEvent<Engine>) => {
await loadStarsPreset(event.detail);
};
const options: ISourceOptions = {
preset: "stars",
background: {
color: "#000000",
},
};
</script>
<Particles
id="stars"
{options}
on:init={handleInit}
/>Particules interactives
Ajoutez de l'interactivité au survol de la souris et au clic :
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
const handleInit = async (event: CustomEvent<Engine>) => {
await loadFull(event.detail);
};
const options: ISourceOptions = {
background: {
color: "#0d0d0d",
},
particles: {
number: { value: 100 },
color: { value: "#00d8ff" },
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 1, max: 4 } },
links: {
enable: true,
distance: 120,
color: "#00d8ff",
opacity: 0.3,
width: 1,
},
move: {
enable: true,
speed: 3,
},
},
interactivity: {
events: {
onHover: {
enable: true,
mode: "grab",
},
onClick: {
enable: true,
mode: "push",
},
},
modes: {
grab: {
distance: 180,
links: { opacity: 0.5 },
},
push: {
quantity: 4,
},
},
},
};
</script>
<Particles
id="interactive"
{options}
on:init={handleInit}
/>Gestion des événements
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Container, Engine } from "@tsparticles/engine";
let container: Container;
const handleInit = async (event: CustomEvent<Engine>) => {
await loadFull(event.detail);
};
const handleLoaded = (event: CustomEvent<Container>) => {
container = event.detail;
console.log("Conteneur chargé", container);
};
const pause = () => container?.pause();
const resume = () => container?.play();
const destroy = () => container?.destroy();
</script>
<div>
<button on:click={pause}>Pause</button>
<button on:click={resume}>Reprendre</button>
<button on:click={destroy}>Détruire</button>
</div>
<Particles
id="tsparticles"
options={options}
on:init={handleInit}
on:particlesLoaded={handleLoaded}
/>| Événement | Détail | Se déclenche |
|---|---|---|
on:init | Engine | Après l'initialisation du moteur |
on:particlesLoaded | Container | Lorsque le conteneur est prêt |
Exemple TypeScript
Composant typé complet :
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type {
Container,
Engine,
ISourceOptions,
} from "@tsparticles/engine";
let particlesContainer: Container | undefined;
const options: ISourceOptions = {
background: {
color: "#1e1e2e",
},
fpsLimit: 60,
particles: {
color: {
value: "#cdd6f4",
},
links: {
color: "#cdd6f4",
distance: 150,
enable: true,
opacity: 0.3,
width: 1,
},
move: {
enable: true,
speed: 1.5,
},
number: {
value: 60,
},
opacity: {
value: 0.6,
},
size: {
value: { min: 1, max: 3 },
},
},
interactivity: {
events: {
onHover: {
enable: true,
mode: "repulse",
},
},
modes: {
repulse: {
distance: 100,
},
},
},
detectRetina: true,
};
const handleInit = async (event: CustomEvent<Engine>) => {
await loadFull(event.detail);
};
const handleLoaded = (event: CustomEvent<Container>) => {
particlesContainer = event.detail;
};
</script>
<Particles
id="tsparticles"
{options}
on:init={handleInit}
on:particlesLoaded={handleLoaded}
/>Options dynamiques
Les options réactives mettent à jour les particules sans recréer l'instance :
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
let color = "#ff0000";
const handleInit = async (event: CustomEvent<Engine>) => {
await loadFull(event.detail);
};
$: options = {
background: {
color: "#000000",
},
particles: {
color: {
value: color,
},
links: {
color: color,
enable: true,
distance: 150,
},
number: {
value: 60,
},
move: {
enable: true,
speed: 2,
},
size: {
value: { min: 1, max: 3 },
},
},
} satisfies ISourceOptions;
</script>
<div>
<label>
Couleur des particules :
<input type="color" bind:value={color} />
</label>
</div>
<Particles
id="dynamic"
{options}
on:init={handleInit}
/>La déclaration réactive $: recalcule options à chaque changement de color, et le composant Particles récupère la nouvelle configuration automatiquement.
Instances multiples
Affichez plusieurs systèmes de particules indépendants sur la même page :
<script lang="ts">
import Particles from "@tsparticles/svelte";
import { loadFull } from "tsparticles";
import type { Engine, ISourceOptions } from "@tsparticles/engine";
const handleInit = async (event: CustomEvent<Engine>) => {
await loadFull(event.detail);
};
const fireOptions: ISourceOptions = {
background: { color: "#1a0000" },
particles: {
color: { value: "#ff4500" },
number: { value: 40 },
move: { enable: true, speed: 1 },
size: { value: { min: 2, max: 6 } },
opacity: { value: 0.8 },
},
};
const waterOptions: ISourceOptions = {
background: { color: "#000d1a" },
particles: {
color: { value: "#00bfff" },
number: { value: 60 },
move: { enable: true, speed: 0.5, direction: "top" },
size: { value: { min: 1, max: 3 } },
opacity: { value: 0.5 },
},
};
</script>
<div style="display: grid; grid-template-columns: 1fr 1fr; height: 100vh;">
<div style="position: relative;">
<Particles id="fire" options={fireOptions} on:init={handleInit} />
</div>
<div style="position: relative;">
<Particles id="water" options={waterOptions} on:init={handleInit} />
</div>
</div>Chaque composant <Particles> reçoit son propre id, canvas et contexte moteur.
Utilisation avec SvelteKit
Dans SvelteKit, le canvas nécessite l'environnement du navigateur. Désactivez le SSR pour le composant :
<script lang="ts">
import { browser } from "$app/environment";
import { onMount } from "svelte";
let Component: typeof import("@tsparticles/svelte").default;
onMount(async () => {
if (browser) {
const module = await import("@tsparticles/svelte");
Component = module.default;
}
});
</script>
{#if Component}
<svelte:component this={Component} id="tsparticles" options={options} />
{/if}Ou encapsulez l'importation dans un composant client-only. Pour SvelteKit 2+, vous pouvez également utiliser les exclusions SSR de vite-plugin-svelte.
Référence API
| Prop | Type | Défaut | Description |
|---|---|---|---|
id | string | "tsparticles" | ID de l'élément canvas |
options | ISourceOptions | {} | Objet de configuration des particules |
url | string | — | URL d'une configuration JSON distante |
theme | string | — | Theme name (requires @tsparticles/plugin-themes; safe no-op otherwise). |
| Événement | Détail | Description |
|---|---|---|
on:init | Engine | Se déclenche quand le moteur est initialisé (utilisez pour charger des plugins) |
on:particlesLoaded | Container | Se déclenche quand le conteneur est complètement prêt |
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.
Dépannage
- Canvas non visible — Assurez-vous que le conteneur parent a des dimensions explicites (
height: 100%,height: 100vh, ou une valeur de pixels fixe). loadFull n'est pas une fonction— Vérifiez quetsparticlesest installé et que vous importezloadFulldepuistsparticles(pas depuis@tsparticles/engine).- La réactivité ne fonctionne pas — Assurez-vous que
optionsest une variable réactive ($:ouletliée à une source réactive). Les valeursconstsimples ne seront pas mises à jour. - SvelteKit écran blanc — Importez
@tsparticles/sveltedynamiquement ou utilisez la protectionbrowsercomme montré dans la section SvelteKit ci-dessus. - Erreurs TypeScript pour
event.detail— Utilisez les typesCustomEvent<Engine>etCustomEvent<Container>pour les gestionnaires d'événements.
