Atmosphère✨ Premium

Attraction Field

80 particules attirées vers le curseur avec F = min(2, 50/d) — liaisons entre voisins à < 80 px, amortissement 0,96 par frame, enroulement toroïdal.

JSCanvasInteractive

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 — Fond interactif pour SaaS data ou réseau — Attraction Field exemple 1

① Hero / Landing — Fond interactif pour SaaS data ou réseau

QuandLa landing page présente un outil d'analytique, de cartographie de connexions ou de réseau — l'effet renforce le propos visuel sans image externe.
PourquoiLes particules qui convergent vers le curseur créent une métaphore de centralisation des données et invitent l'utilisateur à interagir, augmentant le temps passé sur la page.
Réglages80 particules, couleur rgba(139,92,246,...). Superposez un scrim rgba(10,10,15,0.55) entre le canvas et le texte pour garantir un ratio de contraste ≥ 4,5:1 sur le titre.
Canvas de brainstorming — Les idées gravitent vers votre focus — Attraction Field exemple 2

② Canvas de brainstorming — Les idées gravitent vers votre focus

QuandUne application de réflexion collaborative (mind map, espace FigJam-like) ouvre une toile vierge — les particules matérialisent des idées qui s'attirent vers le point de concentration de l'utilisateur.
PourquoiLa métaphore physique est directe : chaque particule est une pensée, les liaisons sont des connexions conceptuelles. L'attraction vers le curseur traduit l'acte même de « focaliser » sur une idée, rendant l'espace visuel vivant et expressif.
Réglages80 particules, couleur rgba(139,92,246,...), seuil de liaison 80 px, amortissement 0,96. Pour un rendu plus aéré rappelant un espace créatif ouvert, étendez le seuil à 100 px et réduisez l'opacité des liaisons à 0,10 pour des connexions encore plus subtiles.
Micro-interaction de conversion — Arrière-plan de page de pricing ou modal d'upgrade — Attraction Field exemple 3

③ Micro-interaction de conversion — Arrière-plan de page de pricing ou modal d'upgrade

QuandLa page de pricing ou un modal d'upgrade affiche le plan Pro — l'effet tourne en fond discret pour orienter visuellement le regard vers le CTA.
PourquoiLa gravitation des particules vers le curseur crée un sous-texte visuel de « tout converge ici » au moment précis où l'utilisateur évalue son choix.
RéglagesRéduire le nombre de particules à 40 (e < 40) et augmenter la force à 80 (80/d) pour un comportement plus dramatique et lisible sur une zone réduite.

Comment ça marche

Un IIFE initialise un canvas pleine-largeur via setupCanvas('psAttraction') (lookup getElementById). Un pool de 80 particules est créé au démarrage avec des positions aléatoires, une vitesse nulle et un rayon aléatoire entre 1 et 3 px. Le curseur est suivi par un écouteur mousemove sur le canvas, avec conversion des coordonnées CSS → coordonnées canvas via getBoundingClientRect(). Un requestAnimationFrame non annulable tourne en continu — il n'y a ni IntersectionObserver ni pause hors-viewport.

À chaque frame, chaque particule calcule le vecteur vers le curseur (dx, dy) et la distance d. La force d'attraction vaut F = min(2, 50/d) — croissante à courte portée, plafonnée à 2 pour éviter l'instabilité numérique. L'accélération appliquée est F × 0,02, soit au maximum 0,04 px/frame². La vitesse est amortie à chaque frame par un facteur 0,96 (arrêt naturel en ~25 frames si la force cesse). La position est ensuite mise à jour, puis enroulée toroïdalement : une particule qui sort par un bord réapparaît au bord opposé.

Le rendu commence par un fond plein #0a0a0f (fillRect total, pas de clearRect). Chaque particule est dessinée comme un cercle rgba(139, 92, 246, 0,4 + r/5) — les petites particules (r ≈ 1) ont une opacité de 0,6 ; les grandes (r ≈ 3) atteignent 1,0. Une double boucle parcourt ensuite toutes les paires : si la distance entre deux particules est inférieure à 80 px, une liaison de 0,5 px d'épaisseur est tracée avec une opacité 0,15 × (1 − d/80) — les connexions s'estompent graduellement avec la distance.

Accessibilité

  • prefers-reduced-motion absent : le code ne vérifie pas cette préférence média — l'animation tourne en boucle perpétuelle quel que soit le réglage système. Ajoutez un garde matchMedia('(prefers-reduced-motion: reduce)') manuellement pour les projets accessibles.
  • Le <canvas> ne porte pas d'aria-hidden="true" dans la structure fournie — à ajouter pour que les lecteurs d'écran ignorent l'élément canvas.
  • Pas de role="img" ni d'aria-label sur le conteneur .demo-preview — l'effet n'a aucune description sémantique accessible.
  • L'attraction est déclenchée uniquement par mousemove — aucun équivalent tactile (touchmove) ni clavier. Sur mobile, les particules dérivent vers le centre par défaut.
  • Contraste des particules : #8b5cf6 violet sur fond #0a0a0f atteint ~4,7:1 à pleine opacité (WCAG AA pour éléments graphiques) ; les liaisons à alpha 0,15 restent sous le seuil — elles sont décoratives, pas informationnelles.

Compatibilité navigateur

Nécessite Canvas 2D Context et requestAnimationFrame — supportés dans tous les navigateurs modernes. Aucune dépendance externe.

Chrome 88+✓ Complet
Firefox 87+✓ Complet
Safari 15+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Centre fixe (pas de mousemove)
Android Chrome✓ Centre fixe (pas de mousemove)

Si <code>canvas</code> n'est pas supporté, le conteneur reste vide (aucune erreur JS fatale). Si <code>getElementById('psAttraction')</code> ne trouve pas le canvas, l'IIFE retourne immédiatement sans lancer de boucle.

Le code

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

index.html — structure
<div class="demo-preview">
  <div class="ps-canvas-wrap" role="img" aria-label="Particules violettes attirées vers le curseur avec liaisons entre voisins proches">
    <canvas class="ps-canvas" id="psAttraction" aria-hidden="true"></canvas>
    <span class="ps-hint" aria-hidden="true">Bougez la souris</span>
    <!-- Optionnel : overlay de contenu (scrim + titre + CTA) -->
    <!-- <div class="ps-overlay"> ... </div> -->
  </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 [JS : < 80] 80 Boucle de spawn : for (let e = 0; e < 80; e++). 40–60 est plus adapté à un composant embarqué ; dépasser 120 pèse sur les navigateurs mobiles.
Rayon des particules [JS : 2 × rand + 1] 1 – 3 px Contrôle taille et opacité (opacité = 0,4 + r/5). Remplacer par rand + 0.5 pour un rendu plus fin ; 3 × rand + 2 pour des particules grandes et lumineuses.
Constante d'attraction [JS : 50] 50 Numérateur dans min(2, 50/d). Augmenter étend la portée de l'attraction ; réduire la concentre autour du curseur.
Facteur d'accélération [JS : 0.02] 0,02 Multiplie la force à chaque frame : dx/d × force × 0.02. 0,02 donne une attraction fluide ; 0,05 la rend brusque et instable.
Amortissement [JS : 0.96] 0,96 Facteur de décélération par frame : vx *= .96. 0,96 = arrêt naturel en ~25 frames. 0,99 = traîne longue, 0,90 = stop brusque.
Seuil de liaison [JS : 80] 80 px Distance maximum entre deux particules pour tracer une liaison : if (i < 80). Augmenter densifie le graphe ; réduire à 50 l'épure.
Couleur des particules [JS : 139,92,246] violet #8b5cf6 Valeurs RVB dans rgba(139,92,246,...) et rgba(139,92,246,...) (liaisons). Remplacez les trois entiers par les composantes de votre couleur brand.

FAQ

Non : le code ne contient pas d'IntersectionObserver. Le requestAnimationFrame tourne en continu même si le canvas est hors écran. Pour optimiser les performances, encapsulez la boucle dans un IntersectionObserver qui coupe le RAF quand le ratio d'intersection tombe à zéro et le relance au retour.
Dans sa forme actuelle, l'effet écoute uniquement mousemove. Sur mobile, les particules dérivent vers le centre (position par défaut). Pour activer le toucher, ajoutez un écouteur touchmove sur le canvas qui met à jour les variables e et n avec evt.touches[0].clientX et clientY, convertis via getBoundingClientRect().
L'effet utilise un id fixe 'psAttraction'. Dans React, montez le canvas via une ref dans useEffect, extrayez la logique de particules dans une fonction initAttraction(canvas) qui reçoit l'élément canvas en paramètre (pas un id), et annulez le requestAnimationFrame dans la fonction de cleanup. Dans Vue, même principe via onMounted / onUnmounted.