Atmosphère✨ Premium

Fireflies

30 lucioles sur canvas : pulsation sinusoïdale individuelle, mouvement Brownien amorti, halo radial jaune-vert et wrapping torique aux bords.

JSCanvasGlow

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Atmosphère comprend 57 effets, dont 10 gratuits. Découvrir la catégorie →

3 exemples d'usage

Hero / Landing — Soirée plein air — Fireflies exemple 1

① Hero / Landing — Soirée plein air

QuandLanding page d'une app d'événements nocturnes, d'un site de tourisme nature ou d'un service d'observation astronomique, visible dès le premier viewport.
PourquoiLes lucioles créent l'atmosphère « nuit d'été » sans image externe — zéro HTTP request, aucun format à gérer — et le mouvement Brownien reste assez doux pour ne pas concurrencer le titre principal.
Réglages30 particules, vitesse initiale basse : remplacez le préfacteur 0.5 par 0.3 (soit vx/vy ±0,15 px/frame). Halo à son opacité maximale par défaut (0,15×n suffit sur fond très sombre).
Composant produit — Widget biodiversité nocturne — Fireflies exemple 2

② Composant produit — Widget biodiversité nocturne

QuandDashboard d'une app de jardinage, météo ou biodiversité : carte de présence d'espèces nocturnes, alerte « bonnes conditions d'observation » ou résumé d'une sortie nature.
PourquoiL'animation légère (aucun clic, aucun son, halo à 15 % d'opacité) s'intègre dans une carte sans capter l'attention au détriment des données numériques.
RéglagesRéduire à 15 particules (changer 30 en 15) et rayon de base 1 × Math.random() + 1 pour un fond moins dense dans une petite carte.
Micro-interaction de conversion — Confirmation nuit nature — Fireflies exemple 3

③ Micro-interaction de conversion — Confirmation nuit nature

QuandÉcran de confirmation après réservation d'une sortie nature, d'un accès premium à un contenu nocturne ou d'un abonnement à un service environnemental.
PourquoiLes lucioles associent la confirmation à un souvenir estival — renforcement émotionnel de la décision sans animation agressive ni son.
Réglages30 particules (densité maximale), fréquence de pulsation en haut de plage : speed: 0.04 * Math.random() + 0.02 pour des battements légèrement plus vifs au moment de la célébration.

Comment ça marche

setupCanvas("psFireflies") dimensionne le <canvas> sur les dimensions de son conteneur parent via getBoundingClientRect(), puis 30 particules sont créées — chacune avec position aléatoire, vecteur vitesse initial (vx = vy = ±0,25 px/frame max), une phase de départ dans [0, 2π] et une fréquence de pulsation speed dans [0,01 – 0,03] rad/frame.

À chaque frame rAF, une impulsion aléatoire de ±0,025 px est ajoutée à chaque composante de vitesse (bruit de Brown). Un amortissement ×0,98 borne la dérive sans la figer — la luciole ondule organiquement. Aux quatre bords, un wrapping torique téléporte la particule du côté opposé : elle disparaît à droite, réapparaît à gauche.

Chaque luciole possède sa propre fréquence : n = (sin(frame × speed + phase) + 1) / 2. Ce scalaire oscille entre 0 et 1 et module simultanément l'opacité du noyau (0,30 + 0,70×n) et son rayon effectif (size + 2×n). Les 30 phases et fréquences étant indépendantes, les lucioles ne clignotent jamais à l'unisson.

Pour chaque luciole, un createRadialGradient de rayon 6×h dessine le halo — couleur rgba(180,230,80, 0,15×n) au centre vers transparent. Le noyau solide est un arc plein en rgba(200,250,100, 0,30 + 0,70×n). L'effet ne gère ni prefers-reduced-motion, ni IntersectionObserver, ni API publique — c'est un IIFE autonome qui tourne en continu dès le chargement de la page.

Accessibilité

  • prefers-reduced-motion absent : l'effet ne détecte pas la préférence système. L'animation tourne sans condition ; ajoutez window.matchMedia('(prefers-reduced-motion:reduce)').matches pour stopper le RAF si l'accessibilité réduite est requise.
  • Le <canvas> ne porte ni aria-hidden, ni role, ni aria-label dans le code d'origine — ajoutez aria-hidden="true" si l'effet est purement décoratif.
  • Contraste du noyau : rgba(200,250,100) sur fond #0a0a0f dépasse un ratio de luminance 7:1 — au-dessus du seuil AAA pour les composants graphiques.
  • Aucune interaction clavier ni pointeur n'est enregistrée — le canvas ne reçoit pas le focus, la navigation au clavier sur la page n'est pas impactée.
  • Effet purement décoratif : aucun contenu textuel ni informatif ne réside dans le canvas — le contenu overlay associé (titre, CTA) doit vivre dans le DOM, pas dans le canvas.

Compatibilité navigateur

Requiert Canvas 2D et requestAnimationFrame — supportés dans tous les navigateurs modernes. Zéro dépendance externe.

Chrome 88+✓ Complet
Firefox 87+✓ Complet
Safari 15+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Complet
Android Chrome✓ Complet

Sans support <code>canvas</code>, le conteneur parent s'affiche avec son fond — aucune erreur JS fatale, le reste de la page reste fonctionnel.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="ps-scene" role="img" aria-label="Lucioles animées en vol nocturne">
  <div class="ps-canvas-wrap">
    <canvas class="ps-canvas" id="psFireflies" aria-hidden="true"></canvas>
  </div>

  <!-- Facultatif : scrim + contenu overlay -->
  <div class="ps-scrim" aria-hidden="true"></div>
  <div class="ps-overlay">
    <h2 class="ps-overlay-title">Votre message</h2>
    <button class="ps-overlay-cta">CTA</button>
  </div>
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Nombre de particules (for e < 30) 30 Nombre de lucioles simultanées. 10–15 pour un fond discret dans une petite carte, 50–60 pour une scène plein-écran dense.
Vitesse initiale (0.5 × (random − 0.5)) ±0,25 px/frame Changez le préfacteur 0.5 pour moduler la dérive de départ. 0,3 = vol lent et posé, 0,8 = vol rapide et nerveux.
Bruit Brownien (0.05 × (random − 0.5)) ±0,025 px/frame Amplitude de l'impulsion aléatoire ajoutée à chaque frame. 0,02 = trajectoire quasi linéaire, 0,10 = vol très erratique et saccadé.
Amortissement (vx *= 0.98) 0.98 Facteur de dissipation de vitesse. 0,96 = décélération rapide (petits trajets), 0,995 = glissement quasi inertiel (longues trajectoires douces).
Fréquence de pulsation (0.02 × random + 0.01) [0,01 – 0,03] rad/frame Plage de vitesses de clignotement. 0.04 × random + 0.02 pour des battements vifs, 0.008 × random + 0.004 pour une respiration très lente.
Rayon de base (2 × random + 1.5) [1,5 – 3,5] px Taille des noyaux. 1 × random + 1 = insectes très petits, 3 × random + 2 = points plus visibles sur fond moins sombre.
Teinte du halo (rgba(180,230,80,…)) jaune-vert #b4e650 Couleur du dégradé radial. rgba(80,180,230,…) pour un halo bleu électrique, rgba(255,160,40,…) pour une lueur ambre.
Rayon du halo (6 × h) 6× le rayon effectif Multiplicateur de la taille du dégradé. 4× = halo serré et ponctuel, 10× = aura large et vaporeuse autour du noyau.

FAQ

Le code utilise deux constantes : le halo rgba(180,230,80,…) et le noyau rgba(200,250,100,…). Remplacez les deux par vos valeurs RVB — par exemple rgba(80,180,230,…) et rgba(100,210,255,…) pour des lucioles bleues, ou rgba(255,160,40,…) et rgba(255,200,80,…) pour un rendu ambre.
Partiellement : les navigateurs suspendent requestAnimationFrame quand l'onglet n'est pas actif (zéro CPU). En revanche, l'effet n'implémente pas d'IntersectionObserver — il continue de tourner si la section est hors du viewport mais l'onglet reste au premier plan. Ajoutez un IntersectionObserver sur le canvas pour stopper le RAF hors-écran.
Non dans son état d'origine : le IIFE cible l'id fixe psFireflies via getElementById — une seule instance est possible. Pour plusieurs instances, extrayez la logique dans une fonction paramétrée par l'id du canvas et appelez-la une fois par composant.