Water Ripple
Une eau bleu nuit, lisse et immobile, où chaque clic lâche une perturbation qui s'étale en cercles, rebondit sur les bords et croise les ondes des autres clics : une vraie équation des ondes sur une grille de hauteurs, recalculée pixel par pixel — 4,7 Ko de JavaScript, net sur écran Retina, à l'arrêt quand l'eau est calme.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Liquid comprend 31 effets, dont 6 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Le bloc .fx-0392-root fait 300 px de haut et toute la largeur disponible. Son conteneur .water-ripple-container (curseur en main) porte un <canvas class="water-ripple-canvas"> en display: block à 100 % du cadre, et une ligne d'aide en bas, « Cliquez pour créer des ondulations ». La hauteur est fixée par le CSS de la racine et le canvas se cale dessus : 20 redimensionnements de suite, 0 px de dérive (Chromium et Firefox). L'eau au repos est un bleu nuit uni, rgb(10, 45, 100).
Le script tient deux grilles de hauteurs (Float32Array), l'état présent et le précédent, une case par pixel du canvas. Un clic pose un disque de 5 px de rayon dont la hauteur vaut 500 au centre et décroît jusqu'au bord. À chaque image, chaque case prend la moyenne de ses quatre voisines dans l'état précédent, multipliée par 2, moins sa propre valeur, puis perd 1 % (damping = 0.99) : c'est la forme discrète de l'équation des ondes. La perturbation s'étale en anneaux, se réfléchit sur les bords (les cases du bord restent à 0) et les anneaux de plusieurs clics se croisent sans se gêner. Le rendu lit chaque hauteur : une crête éclaircit le bleu (jusqu'à 255), un creux l'assombrit, et le rouge monte avec l'amplitude, d'où le liseré violet au point d'impact.
La boucle ne tourne que pendant une onde. Au repos, aucune image n'est calculée (0 appel à requestAnimationFrame par seconde, mesuré) ; après un clic, elle s'arrête d'elle-même quand la plus forte hauteur repasse sous 0,5, soit environ 900 images (15 s à 60 Hz), puis remet la grille à zéro. Elle se suspend aussi hors écran (IntersectionObserver) et onglet caché. Sur écran Retina, la grille compte 2 cases par pixel CSS tant qu'elle reste sous 800 000 cases (un bloc de 640 × 300 donne 1 280 × 600, net) ; le script fait alors 2 pas de calcul par image, avec un amortissement de 0,99 partagé entre les deux, pour que l'onde avance et s'éteigne au même rythme à l'œil. Mesuré pendant une onde : 1,1 ms par image dans Chromium, 1 ms dans Firefox et WebKit à 640 × 300 ; 6, 9 et 5 ms sur Retina. Le script anime chaque .fx-0392-root de la page séparément.
Accessibilité
- Mouvement réduit : sous
prefers-reduced-motion: reduce, un clic ne lance pas d'onde. Une tache claire de 16 px de rayon apparaît sous le pointeur et s'éteint sur place en une quarantaine d'images (0,7 s à 60 Hz), sans anneau qui s'étale ; mesuré dans Chromium et Firefox, la boucle s'arrête d'elle-même ensuite. Au repos, l'eau est immobile dans les deux modes. - Clavier : l'eau réagit au clic (souris ou doigt), pas au clavier. Si le geste déclenche une action (choisir une zone, compter), donnez-lui aussi un bouton ou un lien atteignable au clavier, et annoncez le résultat dans une zone
role="status", comme le compteur et la carte des exemples. - Contenu : le canvas ne dit rien aux lecteurs d'écran. Le texte d'aide « Cliquez pour créer des ondulations » est un vrai texte ; dans une interface réelle, remplacez-le par une consigne qui dit à quoi sert le geste.
- Contraste : le texte d'aide, blanc à 50 % sur le bleu nuit, atteint 4,45:1 (calculé), juste sous le seuil de 4,5:1 pour un petit texte : passez-le à 60 % d'opacité s'il porte une consigne utile. Un texte posé sur l'eau reste lisible tant que les ondes passent dessous : elles ne varient le fond que de quelques teintes de bleu.
Compatibilité navigateur
Canvas 2D (createImageData, putImageData), Float32Array, ResizeObserver, IntersectionObserver, matchMedia : 4,7 Ko de JavaScript, aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : même onde, même réflexion sur les bords, canvas à 1 280 × 600 sur écran Retina, arrêt de la boucle au repos, tache fixe sous mouvement réduit, 0 erreur. Les pas de calcul sont comptés par image affichée : sur un écran à 120 Hz, l'onde s'étale deux fois plus vite qu'à 60 Hz.
Sans ResizeObserver, le script suit l'événement resize de la fenêtre ; sans IntersectionObserver, une onde continue de se calculer hors écran jusqu'à s'éteindre. Sans JavaScript, le cadre reste vide avec son texte d'aide : prévoyez un fond de secours sur .water-ripple-container si l'eau doit se voir.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0392-root">
<div class="water-ripple-container">
<canvas class="water-ripple-canvas"></canvas>
<span class="water-hint">Cliquez pour créer des ondulations</span>
</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 |
|---|---|---|
Amortissement (JS — damping, calculé à partir de 0.99) |
0,99 : l'onde perd 1 % par image | 0.98 éteint l'onde en deux fois moins de temps, cercles plus courts ; 0.995 la laisse rebondir longtemps d'un bord à l'autre. Restez sous 1, sinon l'eau ne se calme jamais. |
Taille et force de la goutte (JS — (still ? 16 : 5) * scale et 500) |
disque de 5 px de rayon (16 px en mouvement réduit), hauteur 500 | Un rayon de 10 au lieu de 5 donne des anneaux plus larges et plus doux ; une hauteur de 250, des cercles plus discrets. Le bleu plafonne dès qu'une crête dépasse 155 : au-delà, seul le rouge monte et l'impact vire au violet. |
Couleurs de l'eau (JS — fonction render) |
repos rgb(10, 45, 100) ; crête vers le bleu vif | Le bleu vaut 100 + value, le vert (150 + value / 2) × 0,3, le rouge 10 + |value| × 0,2. Pour une eau turquoise, montez le facteur du vert à 0.8 ; pour une eau sombre, baissez le 100 du bleu à 60. |
Netteté sur Retina (JS — var PIXEL_BUDGET = 800000) |
800 000 cases au plus | Au-delà (bloc plus grand que 200 000 pixels CSS, environ 640 × 310), la grille passe à une case par pixel CSS, un peu moins nette mais avec 4 fois moins de cases à calculer. Montez la valeur pour un grand bloc net sur ordinateur. |
Hauteur (CSS — height de .fx-0392-root) |
300px | Le canvas suit la hauteur du bloc. Pour une eau plein écran, placez la racine en position: absolute; inset: 0. |
Texte d'aide (HTML — .water-hint) |
« Cliquez pour créer des ondulations » | Remplacez-le par la consigne de votre interface, ou masquez-le (display: none) si la page explique déjà le geste. |
FAQ
click du conteneur. Appelez le même code sur pointermove avec une hauteur faible (50 au lieu de 500), au plus une fois toutes les 50 ms, pour un sillage qui suit le pointeur. La boucle repart d'elle-même à chaque goutte et s'arrête quand l'eau redevient calme.