SVG✨ Premium

Maze Generator

Un labyrinthe se creuse sous vos yeux, case par case, par l'algorithme du retour sur trace ; terminé, il laisse place à un nouveau deux secondes plus tard.

CanvasAlgorithmRecursive

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

Fond du hero d'un club de course d'orientation — Maze Generator exemple 1

① Fond du hero d'un club de course d'orientation

QuandSur la page du CO Vaulsenne, le labyrinthe se creuse sur toute la largeur derrière le titre, la carte « Prochaine course » et le bouton d'inscription.
PourquoiDes couloirs qui bifurquent et reviennent sur leurs pas évoquent le choix d'itinéraire, le cœur de la course d'orientation ; le mouvement lent anime la page sans gêner la lecture.
RéglagesRacine en position:absolute; inset:0 avec --mzg-height:100% et filter: hue-rotate(150deg) saturate(1.2) pour passer du violet à l'orange du club sans toucher au script ; voile en dégradé de 95 % à 10 % sous le texte ; canvas en aria-hidden="true".
Figure animée dans un article qui explique l'algorithme — Maze Generator exemple 2

② Figure animée dans un article qui explique l'algorithme

QuandSur le blog Cribelle, l'article « Comment un ordinateur creuse un labyrinthe » décrit la méthode, et la figure 1 la montre en train de tourner, avec une légende qui explique la case rose.
PourquoiLe texte et la figure disent la même chose : le lecteur voit la case rose avancer puis reculer au moment où il lit le paragraphe, ce qu'aucun schéma fixe ne montre.
RéglagesRacine dans un bloc de 262 × 136 px (21 × 11 cases), soit un labyrinthe complet en 1,5 s environ puis 2 s de pause. Canvas gardé en role="img" avec un libellé : ici, la figure fait partie du contenu.
Petit indicateur pendant le calcul d'un itinéraire de randonnée — Maze Generator exemple 3

③ Petit indicateur pendant le calcul d'un itinéraire de randonnée

QuandDans l'appli Draverne, un clic sur « Calculer l'itinéraire » affiche une bande de 252 × 74 px où un labyrinthe se creuse, avec « Recherche parmi les sentiers… », jusqu'à l'arrivée du résultat.
PourquoiUn chemin qui cherche sa route illustre exactement ce qui se passe pendant l'attente, et un labyrinthe de 20 × 6 cases se renouvelle assez vite pour occuper quelques secondes.
RéglagesLa zone d'attente est masquée (hidden) jusqu'au clic ; le code vendu démarre dès qu'elle a une taille. Le script de la scène ne fait qu'alterner les trois états (repos, attente, résultat).

Comment ça marche

La zone est découpée en cases de 12 px, centrées, toutes fermées par quatre murs. L'algorithme part de la case en haut à gauche et garde une pile de son chemin : à chaque étape, il choisit au hasard une voisine jamais visitée, abat le mur qui les sépare et avance ; s'il n'en reste aucune, il dépile et recule. Quand la pile est vide, toutes les cases ont été visitées et il existe exactement un chemin entre deux cases quelconques : c'est un labyrinthe dit « parfait ».

Le rythme est de 300 étapes par seconde, compté en temps écoulé (plafonné à 50 ms par image), donc identique à 60 et à 120 Hz. Il faut environ deux étapes par case : une zone de 800 × 300 px (66 × 24 cases) se creuse en une dizaine de secondes. La case en cours est peinte en rose #d946ef, les cases déjà creusées en violet transparent, les murs en #6366f1. Une fois fini, le dessin reste affiché PAUSE millisecondes (2 000 par défaut), puis une nouvelle grille repart de zéro.

Les murs sont regroupés dans un seul tracé, et les cases creusées dans un seul remplissage, ce qui garde chaque image légère. La taille vient de la zone affichée, multipliée par devicePixelRatio, et les traits sont décalés d'un demi-pixel pour rester nets ; un ResizeObserver relance un labyrinthe adapté quand la zone change de taille, et rien ne démarre tant qu'elle mesure moins d'une case (onglet ou accordéon fermé). Un IntersectionObserver arrête la boucle hors écran. Chaque racine a son propre labyrinthe, lancé une seule fois (data-mzg-ready) même si le script est collé deux fois.

Accessibilité

  • Libellé : role="img" et aria-label sur le canvas. En fond décoratif ou en indicateur accompagné d'un texte, passez-le en aria-hidden="true".
  • Mouvement réduit : sous prefers-reduced-motion: reduce, le labyrinthe est creusé d'un coup et affiché terminé, sans case rose et sans renouvellement.
  • Pause : l'animation se renouvelle sans fin. Pour le critère WCAG 2.2.2, un bouton qui bascule l'attribut hidden de la racine l'arrête ; elle reprend à la même étape.
  • Pas un jeu : le labyrinthe ne se parcourt pas, ni à la souris ni au clavier. Le présenter comme un jeu à résoudre serait trompeur.
  • Clavier : aucun élément interactif, aucun focus à gérer.

Compatibilité navigateur

Canvas 2D et environ 5,6 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 : aucune erreur même quand la zone est masquée au chargement, rendu à densité 2, deux labyrinthes indépendants, labyrinthe terminé 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, un nouveau labyrinthe n'est relancé qu'au redimensionnement de la fenêtre ; sans IntersectionObserver, il continue de se creuser hors écran. Sans JavaScript, la zone garde 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-0617-root">
  <canvas class="mzg-canvas" role="img" aria-label="Labyrinthe en train d'être creusé case par case"></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
Taille des cases (JS — CELL) 12 px 8 px donne un labyrinthe fin et long à creuser, 20 px de larges couloirs lisibles en vignette.
Vitesse (JS — STEPS_PER_S) 300 étapes par seconde 60 pour suivre chaque mouvement de la case rose (pédagogie), 1 500 pour un remplissage quasi instantané.
Pause entre deux labyrinthes (JS — PAUSE) 2000 ms Infinity garde le labyrinthe terminé à l'écran sans en relancer un autre.
Murs (JS — WALL) #6366f1 Toute couleur CSS ; le trait fait 1 px à toutes les densités d'écran.
Cases creusées (JS — VISITED) rgba(99, 102, 241, 0.2) transparent ne montre que les murs, une opacité de 0.4 fait mieux ressortir le chemin parcouru.
Case en cours (JS — HEAD) #d946ef Couleur du curseur qui creuse ; elle disparaît quand le labyrinthe est fini.
Palette entière (CSS — filter sur la racine) aucun hue-rotate(150deg) fait passer violet et rose à l'orange et au vert sans modifier le script.
Fond et hauteur (CSS — background et --mzg-height) #0a0a0f, 300px Le canvas est transparent ; la hauteur accepte toute valeur fixe ou 100% dans un parent de hauteur connue.

FAQ

Aucune ouverture n'est dessinée dans le cadre. Comme le labyrinthe est parfait, n'importe quelle paire de cases est reliée par un seul chemin : pour en faire un jeu, il suffirait d'ouvrir le mur extérieur de deux cases en ajoutant une ligne à la fin de newMaze() (par exemple grid[0].walls[3] = false;), mais la solution n'est ni calculée ni affichée.
Oui : mettez PAUSE à Infinity. Le dernier labyrinthe reste à l'écran et la boucle continue simplement de le redessiner. Un changement de taille de la zone en relance tout de même un nouveau.
Environ deux étapes par case, à 300 étapes par seconde : 0,8 s pour 20 × 6 cases, une dizaine de secondes pour 66 × 24, à quoi s'ajoutent les 2 s de pause. Divisez la surface par quatre (cases deux fois plus grandes) et le temps est divisé par quatre.