Collision Detection
Huit sphères colorées générées à l'initialisation rebondissent en continu dans la zone qui leur est allouée : chaque trame détecte les collisions cercle-à-cercle et les collisions avec les murs, puis échange les vélocités. Simulation autonome sans interaction utilisateur, boucle suspendue hors écran.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Hover comprend 48 effets, dont 5 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La racine .fx-0387-root centre la zone de collision .fx-0387-area, un conteneur de 100 % de large × 300 px. À l'initialisation, huit div.fx-0387-ball sont créés avec un rayon aléatoire (12–22 px), une couleur HSL aléatoire et une vélocité initiale de ±4 px par trame à 60 fps. Leurs positions de départ sont tirées aléatoirement dans le conteneur de façon non superposée.
À chaque trame, la boucle déplace chaque balle selon sa vélocité (mise à l'échelle par le temps écoulé depuis la trame précédente, borné à 50 ms pour éviter les sauts après un onglet en arrière-plan). Elle vérifie les bords du cadre (rebond simple : inversion du signe de la composante correspondante) puis cherche les collisions entre chaque paire de balles : si la distance entre centres est inférieure à la somme des rayons, les vélocités sont recalculées selon l'angle de collision.
Un IntersectionObserver observe la racine : la boucle requestAnimationFrame s'arrête quand la zone sort de l'écran et repart à son retour, sans image calculée hors écran. Sous mouvement réduit, les balles s'affichent à leur position initiale sans boucle.
Accessibilité
- Mouvement réduit : sous
prefers-reduced-motion: reduce, la boucle ne démarre pas. Les balles s'affichent à leur position initiale, visibles sur fond sombre. Aucun contenu informationnel n'est porté par l'animation. - Rôle décoratif : l'animation est purement visuelle. Elle ne porte aucune information accessible par d'autres moyens. Si les balles représentent des entités nommées (molécules, projets), ces noms doivent être exposés en texte à côté de la zone d'animation.
- Clavier et toucher : aucune interaction utilisateur n'est prévue dans cet effet — les balles se déplacent de façon autonome. Il n'y a pas d'élément focusable ni de gestionnaire de toucher.
- Hors écran : la boucle s'arrête automatiquement quand la zone sort de l'écran. Sur un onglet masqué, le navigateur suspend lui-même les
requestAnimationFrame.
Compatibilité navigateur
JavaScript ES5 (requestAnimationFrame, IntersectionObserver, matchMedia), aucune dépendance. IntersectionObserver disponible depuis Chrome 51, Firefox 55 et Safari 12.1. Non mesuré dans Firefox et WebKit.
Sans JavaScript, le cadre reste vide. Sans IntersectionObserver, la boucle tourne aussi hors écran. Sans matchMedia, l'animation démarre même sous mouvement réduit.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0387-root"><div class="physics-container"><div class="fx-0387-area"></div></div></div>
Paiement unique, sans abonnement — le code est à toi pour toujours
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Nombre de balles (JS — boucle for (var n = 0; n < 8; n++)) |
8 balles | 4 balles donnent une simulation plus aérée, 16 un cadre très chargé avec des collisions fréquentes. |
Plage de tailles (JS — var r = 25 + 20 * Math.random()) |
Rayon entre 12,5 et 22,5 px | Augmentez le premier terme pour des sphères plus grandes, réduisez le second pour des tailles plus uniformes. |
Vitesse initiale (JS — vx: (Math.random() - 0.5) * 4) |
±2 px par trame à 60 fps | Multipliez par 2 pour doubler la vitesse. Les rebonds restent corrects quelle que soit la vitesse. |
Couleurs (JS — 'hsl(' + Math.round(360 * Math.random()) + ',70%,60%)') |
Teinte aléatoire, saturation 70 %, luminosité 60 % | Remplacez par une liste fixe de couleurs hexadécimales pour une palette maîtrisée : ['#6366f1','#a855f7','#ec4899'][n % 3]. |
Hauteur de la zone (CSS — .physics-container { height: 300px }) |
300 px (la largeur suit toujours le conteneur) | Augmentez ou réduisez la valeur CSS pour adapter la zone à votre mise en page. La largeur est lue dynamiquement à l'initialisation et mise à jour au redimensionnement. |
FAQ
clientWidth et clientHeight de .fx-0387-area, mises à jour automatiquement au redimensionnement.click sur chaque el à l'initialisation. L'élément DOM est accessible dans la closure via le tableau balls.