SVG✨ Premium

Lissajous Curves

Un point lumineux parcourt une courbe de Lissajous 3 pour 4 et laisse une traînée arc-en-ciel de 500 points qui s'efface en queue, sur un canvas net en Retina.

CanvasMathCurves

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. SVG comprend 30 effets, dont 3 gratuits. Découvrir la catégorie →

3 exemples d'usage

Écran de contrôle sur la fiche d'un module de synthétiseur — Lissajous Curves exemple 1

① Écran de contrôle sur la fiche d'un module de synthétiseur

QuandSur la boutique Vexmorel, la façade du LX-34 est dessinée en CSS et son petit écran XY montre la courbe en train de se tracer, à côté du prix et des caractéristiques.
PourquoiUne figure 3:4 est exactement ce qu'afficherait l'écran d'un double oscillateur : l'animation montre ce que fait le produit au lieu d'une photo figée.
RéglagesRacine dans un écran de 186 × 118 px (--lsj-height:100%), soit une figure de 47 px de demi-hauteur ; grille de graduation en linear-gradient posée par-dessus, transparente au pointeur. Réglages du script par défaut.
Visuel principal du hero d'un cours de maths en ligne — Lissajous Curves exemple 2

② Visuel principal du hero d'un cours de maths en ligne

QuandSur la page d'accueil de Quadrivel, la moitié droite du hero est occupée par la courbe qui se dessine, avec ses équations en légende ; à gauche, le titre, les niveaux et l'essai gratuit.
PourquoiLa figure est une fonction qu'on voit se construire : elle dit « les maths deviennent visibles » mieux qu'une illustration de stock.
RéglagesRacine en position:absolute sur 52 % de la largeur et toute la hauteur ; la figure prend 80 % de la demi-largeur, la plus petite des deux (≈ 112 px). Légende x = sin 3t · y = sin(4t + π/2) recopiée des constantes A et B.
Logo animé dans la barre d'un podcast scientifique — Lissajous Curves exemple 3

③ Logo animé dans la barre d'un podcast scientifique

QuandDans l'en-tête de Sinéphore, une vignette de 48 px tient lieu de logo : la courbe s'y trace en continu, à côté du nom et au-dessus de la liste des épisodes.
PourquoiÀ petite taille, la traînée colorée devient une signature reconnaissable qui parle d'ondes, le sujet du podcast, sans prendre de place.
RéglagesRacine de 48 × 48 px avec coins arrondis (overflow:hidden sur le parent) ; la figure fait 19 px de demi-largeur et les disques gardent leurs 2 px de rayon.

Comment ça marche

À chaque pas, le point est placé en x = sin(A·t), y = sin(B·t + π/2), avec A = 3 et B = 4 : c'est la figure qu'on voit sur un oscilloscope branché en mode XY sur deux sinus de fréquences 3 et 4. Elle se referme tous les 2π, soit 314 pas de 0,02, environ 5,2 s au rythme par défaut de 60 points par seconde. Le rythme est compté en temps écoulé (plafonné à 50 ms par image) : le tracé avance aussi vite sur un écran à 60 Hz qu'à 120 Hz.

Le script garde les 500 dernières positions. À chaque image, il efface 3 % de l'image précédente vers la transparence, puis redessine les 500 points en disques de 2 px : l'opacité monte de 0 pour le plus ancien à presque 1 pour le plus récent, et la teinte avance de 0,5° par point tout en tournant avec le temps. La figure est centrée et occupe 80 % de la plus petite demi-dimension de la zone : sur 800 × 300 px, elle tient dans un carré de 240 px.

La taille vient du canvas affiché (lue sur la zone, multipliée par devicePixelRatio) et un ResizeObserver la suit ; un changement de taille recommence la traînée au centre de la nouvelle zone. Tant que la zone mesure 0 px, rien ne tourne. Un IntersectionObserver arrête la boucle hors écran. Chaque .fx-0612-root de la page a sa propre instance, marquée par data-lsj-ready : coller le script deux fois ne lance pas deux tracés dans la même zone.

Accessibilité

  • Libellé : role="img" et aria-label sur le canvas. En décor pur (logo animé à côté du nom, fond), passez-le en aria-hidden="true".
  • Mouvement réduit : sous prefers-reduced-motion: reduce, la figure complète est dessinée une seule fois, en couleurs pleines, et ne bouge plus.
  • Pause : pas de bouton intégré. Basculer l'attribut hidden de la racine arrête le calcul (taille nulle) et le reprend au réaffichage, ce qui suffit pour offrir le contrôle demandé par le critère WCAG 2.2.2.
  • Couleur : l'arc-en-ciel est décoratif, il ne porte aucune information ; rien n'est à lire dans la courbe.
  • Clavier : aucun élément interactif dans l'effet, aucun focus à gérer.

Compatibilité navigateur

Canvas 2D et environ 4 Ko de JavaScript, sans dépendance. ResizeObserver : Chrome 64, Firefox 69, Safari 13.1 ; IntersectionObserver : Chrome 51, Firefox 55, Safari 12.1 (données MDN). Mesuré dans Chromium 151, Firefox 153 et WebKit 26.5 : rendu à densité 2, deux copies indépendantes, démarrage après un affichage différé, figure fixe en mouvement réduit, aucune image calculée hors écran.

Chrome 64+✓ Complet (mesuré)
Firefox 69+✓ Complet (mesuré)
Safari 13.1+✓ Complet (mesuré dans WebKit)
Edge 79+✓ Complet (moteur Chromium)
Safari iOS 13.4+✓ Complet (WebKit, non vérifié sur appareil)
Chrome Android 64+✓ Complet (moteur Chromium)

Sans ResizeObserver, la figure ne se recentre qu'au redimensionnement de la fenêtre ; sans IntersectionObserver, la boucle continue hors écran. Avant Safari 14, un changement du réglage « réduire les animations » demande un rechargement. Sans JavaScript, la zone reste vide sur le fond de la racine.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :

index.html — structure
<div class="fx-0612-root">
  <canvas class="lsj-canvas" role="img" aria-label="Courbe de Lissajous tracée par un point lumineux qui laisse une traînée arc-en-ciel"></canvas>
</div>

Paiement unique, sans abonnement — le code est à toi pour toujours

Personnaliser

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

Option / propriétéDéfautEffet
Fréquences (JS — A, B) 3 et 4 1 et 2 donnent une simple parabole parcourue en aller-retour, 5 et 4 une figure plus dense. Deux entiers premiers entre eux referment toujours la courbe.
Pas de la courbe (JS — STEP) 0.02 Plus petit, les points se rapprochent et la courbe paraît continue, mais elle avance moins vite.
Vitesse (JS — POINTS_PER_S) 60 points par seconde Doublez-le avec STEP divisé par deux : même vitesse, traînée deux fois plus dense.
Longueur de la traînée (JS — LENGTH) 500 points 300 laisse un serpent court qui ne couvre pas toute la figure ; 800 la garde presque entière.
Taille de la figure (JS — SIZE) 0.8 (80 % de la demi-zone) 0.95 colle aux bords, 0.5 laisse de l'air autour, par exemple pour un logo.
Épaisseur (JS — RADIUS) 2 px 1 pour un trait fin d'oscilloscope, 3 ou 4 pour un rendu plus graphique.
Fond (CSS — background de .fx-0612-root) #0a0a0f Les traînées s'effacent vers la transparence : changez seulement cette couleur. Sur fond clair, les teintes à 60 % de luminosité restent lisibles.
Hauteur (CSS — --lsj-height) 300px Toute hauteur fixe ou 100% dans un parent de hauteur connue ; la figure se recentre seule.

FAQ

Le pas STEP est fixé dans l'équation, pas en pixels : plus la figure est grande, plus deux points successifs s'écartent. Dès 40 px de demi-largeur, les disques se séparent là où la courbe va le plus vite. Pour un grand visuel, divisez STEP par deux ou trois et multipliez d'autant POINTS_PER_S et LENGTH : même vitesse, même longueur de traînée, trait plus continu.
Pas tel quel : la courbe est calculée à partir de deux sinus, elle ne lit aucun son. Pour un oscilloscope réel, il faudrait remplacer le calcul de addPoint() par les échantillons de deux AnalyserNode de la Web Audio API, ce qui sort du périmètre de cet effet.
Non : avec des fréquences entières et une phase fixe de π/2, la forme ne change pas ; seul le point avance et les couleurs défilent. Pour une figure qui se déforme lentement, comme sur un oscilloscope légèrement désaccordé, donnez à B une valeur un peu décimale (4.01 par exemple) : elle ne se refermera plus exactement.