Guide Ember
Table des matières
- Installation
- Initialisation du moteur
- Utilisation de base
- Configuration personnalisée
- Gestion des événements
- Rendu conditionnel
- Exemple TypeScript
Installation
Installez l'addon Ember et le moteur tsParticles via ember-cli :
ember install @tsparticles/emberCeci installera l'addon et sa dépendance directe tsparticles. Vous pouvez optionnellement ajouter des packages de préréglages :
npm install @tsparticles/slimInitialisation du moteur
L'addon exporte un utilitaire initParticlesEngine que vous appelez une fois au niveau de l'application. Il reçoit un callback asynchrone où vous chargez les fonctionnalités, préréglages ou formes dont votre application a besoin.
import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine";
import { loadFull } from "tsparticles";
// Appelez ceci lors du bootstrap de l'application
if (typeof window !== "undefined") {
void initParticlesEngine(async (engine) => {
await loadFull(engine);
});
}Les emplacements typiques pour cet appel sont le hook beforeModel de la route de l'application, le constructeur d'un contrôleur d'application, ou un initialiseur d'instance. Le singleton du moteur est initialisé une fois et partagé entre tous les composants <Particles> de votre application.
Utilisation de base
Après avoir initialisé le moteur, utilisez le composant <Particles> dans n'importe quel template. Passez votre configuration de particules via l'argument @options.
{{! app/templates/application.hbs }}
<Particles @options={{this.options}} />// app/controllers/application.ts
import Controller from "@ember/controller";
import type { ISourceOptions } from "@tsparticles/engine";
export default class ApplicationController extends Controller {
options: ISourceOptions = {
fpsLimit: 60,
particles: {
number: { value: 80 },
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,
width: 1,
},
move: {
enable: true,
speed: 1.5,
direction: "none",
random: true,
outModes: { default: "bounce" },
},
},
background: { color: "#0d1117" },
};
}Configuration personnalisée
Construisez une configuration plus riche avec interactivité, formes multiples et densité réactive.
import Controller from "@ember/controller";
import type { ISourceOptions } from "@tsparticles/engine";
export default class IndexController extends Controller {
options: ISourceOptions = {
fullScreen: { enable: true, zIndex: -1 },
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,
straight: false,
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" },
};
}<Particles @options={{this.options}} />Gestion des événements
Le composant <Particles> déclenche une action @particlesLoaded lorsque le conteneur a fini de s'initialiser et que la première image est rendue. Utilisez-la pour accéder à l'instance Container pour un contrôle programmatique.
import Controller from "@ember/controller";
import { action } from "@ember/object";
import type { Container, ISourceOptions } from "@tsparticles/engine";
export default class ApplicationController extends Controller {
options: ISourceOptions = {
/* ... */
};
@action
loadedCallback(container: Container) {
console.log("Particules chargées", container?.id);
// Exemple de contrôle programmatique :
setTimeout(() => {
container.pause();
console.log("Particules mises en pause après 5 secondes");
}, 5000);
}
}<Particles @options={{this.options}} @particlesLoaded={{this.loadedCallback}} />Vous pouvez également utiliser le modèle de callback en ligne avec un assistant de template si vous préférez ne pas définir d'action séparée.
Rendu conditionnel
Utilisez le helper d'Ember avec une propriété @tracked pour contrôler quand le composant <Particles> est rendu. Ceci est utile lorsque l'initialisation du moteur est asynchrone et que vous voulez éviter de rendre le composant avant que le moteur ne soit prêt.
import Controller from "@ember/controller";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import type { Container, Engine, ISourceOptions } from "@tsparticles/engine";
import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine";
import { loadSlim } from "@tsparticles/slim";
export default class ApplicationController extends Controller {
@tracked engineReady = false;
options: ISourceOptions = {
particles: {
number: { value: 50 },
color: { value: "#ffffff" },
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 1, max: 4 } },
move: { enable: true, speed: 1, outModes: { default: "bounce" } },
},
background: { color: "#1a1a2e" },
};
constructor(...args: any[]) {
super(...args);
if (typeof window !== "undefined") {
void initParticlesEngine(async (engine: Engine) => {
await loadSlim(engine);
}).then(() => {
this.engineReady = true;
});
}
}
}{{#if this.engineReady}}
<Particles @options={{this.options}} @particlesLoaded={{this.loadedCallback}} />
{{else}}
<p>Chargement des particules...</p>
{{/if}}Le décorateur @tracked garantit que le template se ré-affiche automatiquement une fois la promesse résolue.
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.
Exemple TypeScript
Voici un contrôleur d'application Ember complet et typé démontrant le modèle d'intégration complet avec le préréglage slim, l'interactivité et la gestion du cycle de vie.
// app/controllers/application.ts
import Controller from "@ember/controller";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import type { Container, Engine, ISourceOptions } from "@tsparticles/engine";
import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine";
import { loadSlim } from "@tsparticles/slim";
export default class ApplicationController extends Controller {
@tracked private engineReady = false;
private container?: Container;
private readonly options: ISourceOptions = {
fullScreen: { enable: true, zIndex: -1 },
fpsLimit: 60,
particles: {
number: { value: 80, density: { enable: true } },
color: { value: "#6366f1" },
shape: { type: "circle" },
opacity: { value: { min: 0.3, max: 0.7 } },
size: { value: { min: 2, max: 6 } },
links: {
enable: true,
distance: 160,
color: "#6366f1",
opacity: 0.25,
width: 1,
},
move: {
enable: true,
speed: 1.2,
direction: "none",
random: false,
straight: false,
outModes: { default: "bounce" },
},
},
interactivity: {
events: {
onHover: { enable: true, mode: "grab" },
onClick: { enable: true, mode: "push" },
},
modes: {
grab: { distance: 180, links: { opacity: 0.6 } },
push: { quantity: 3 },
},
},
background: { color: "#0a0a1a" },
};
constructor(...args: any[]) {
super(...args);
if (typeof window !== "undefined") {
void initParticlesEngine(async (engine: Engine) => {
await loadSlim(engine);
}).then(() => {
this.engineReady = true;
});
}
}
@action
private handleParticlesLoaded(container?: Container): void {
this.container = container;
console.log("Particules chargées dans le conteneur :", container?.id);
}
}{{! app/templates/application.hbs }}
{{#if this.engineReady}}
<div class="app-container">
<h1>tsParticles + Ember</h1>
<Particles @options={{this.options}} @particlesLoaded={{this.handleParticlesLoaded}} />
</div>
{{else}}
<div class="loading">
<p>Initialisation du moteur de particules...</p>
</div>
{{/if}}Vous avez maintenant tout ce qu'il faut pour intégrer tsParticles dans une application Ember.js. Chaque exemple est autonome et prêt à être copié dans votre projet.
