En 1994, sur Mega Drive et Super Nintendo, le jeu de combat Ballz alignait des combattants tout en sphères. L’année suivante, son studio, PF.Magic, recyclait ce moteur pour Dogz, un chiot virtuel qui gambadait sur l’écran des PC. Une trentaine d’années plus tard, ces boules plates ont un héritier dans le navigateur : Zdog.
Son auteur le dit « directement inspiré » de Dogz. Et il a rappelé en mars 2019 que ce moteur avait d’abord servi à Ballz.
Zdog dessine de la 3D en formes plates, en Canvas ou en SVG, avec 7 Kio de code compressé. Sa dernière version date de janvier 2022, et le projet se présente toujours comme une bêta. Elle tourne pourtant sans broncher dans un navigateur de 2026.
Voici ce qu’il sait faire, ce qui lui manque et une première scène en quelques lignes. Puis notre banc d’essai face à three.js.

Zdog, c’est quoi ?
Zdog n’est pas un logiciel de 3D : c’est une bibliothèque JavaScript, libre sous licence MIT. On la doit à David DeSandro, l’auteur d’Isotope et de Flickity. Il voulait créer un jeu vidéo et cherchait un moteur 3D léger. Il a fini par écrire le sien, avec un but : apporter à la 3D la simplicité de l’illustration vectorielle.
Zdog se prononce « zi-dog » à l’américaine, « zèd-dog » à la britannique. Il dessine des cercles, des rectangles, des polygones, des hémisphères, des cônes, des cylindres et des boîtes. Pour une sphère, on trace un seul point avec un trait très épais.
Selon son auteur, la bibliothèque tient en 2 100 lignes et 28 Ko minifiés. C’est presque juste : la version 1.1.3 en pèse 29 Kio. Compressée en gzip, elle tombe à 7 Kio. La version 1.0.0 a été publiée sur npm le 21 mai 2019. Son dépôt GitHub affiche aujourd’hui 10 700 étoiles.
Comment Zdog fait-il de la 3D avec des formes plates ?
Chaque forme existe dans un espace en trois dimensions. À chaque image, Zdog projette les points de chaque forme sur l’écran. Puis il la dessine comme un simple tracé 2D, aux bords arrondis. Le tout passe par le Canvas 2D ou le SVG, jamais par WebGL. Pas de shaders : rien que les outils de dessin les plus simples du navigateur.
Ce choix a un prix. D’abord, pas de perspective : une boule au loin garde la taille d’une boule toute proche. On l’a vérifié avec deux sphères placées à 300 unités d’écart, rendues au même diamètre.
Ensuite, pas de lumière ni d’ombre. L’API ne connaît que des couleurs unies. Le relief, c’est toi qui le peins. Une teinte plus sombre pour la base d’un hémisphère, une autre pour la face arrière d’un cylindre.
Une première scène en 25 lignes
Un dango, trois boules sur une brochette, suffit à faire le tour des bases. Colle ce code dans un fichier .html et ouvre-le dans ton navigateur.
<canvas class="dango" width="320" height="320"></canvas>
<script src="https://unpkg.com/zdog@1/dist/zdog.dist.min.js"></script>
<script>
const illo = new Zdog.Illustration({ element: '.dango', dragRotate: true });
// la brochette, penchée à 45 degrés
const brochette = new Zdog.Anchor({ addTo: illo, rotate: { z: -Zdog.TAU / 8 } });
// trois boules : un seul point, un trait très épais
['#F4A6B8', '#FBF8F2', '#8DBA6A'].forEach((color, i) => {
new Zdog.Shape({ addTo: brochette, translate: { y: (i - 1) * 58 }, stroke: 56, color });
});
// le bâton, en deux bouts qui partent de la surface des boules
[[-86, -125], [86, 125]].forEach(([from, to]) => {
new Zdog.Shape({ addTo: brochette, path: [{ y: from }, { y: to }], stroke: 6, color: '#B0844C' });
});
function animate() {
illo.rotate.y += 0.02;
illo.updateRenderGraph();
requestAnimationFrame(animate);
}
animate();
</script>
Illustration désigne la zone de dessin. Anchor est un point d’attache invisible, penché ici à 45 degrés. Chaque boule est un point unique, avec un trait de 56 pixels. updateRenderGraph recalcule et redessine la scène à chaque passage de requestAnimationFrame. Et dragRotate laisse la souris faire tourner le tout.
Pour passer en SVG, une seule balise change : <svg class="dango" width="320" height="320"></svg> à la place du <canvas>. Le reste du code ne bouge pas.

Ce que Zdog ne sait pas faire
Zdog ne calcule pas les collisions entre formes. Il trie chacune selon la moyenne de ses points, puis les dessine de l’arrière vers l’avant. Tant que les formes restent séparées, tout va bien. Dès qu’elles se traversent, le tri déraille.
Notre dango en est la preuve. Un bâton d’un seul tenant est trié sur son centre, à hauteur de la boule du milieu. Selon l’angle, il passe alors devant les boules. Coupé en deux bouts qui partent de la surface des boules, chaque morceau retrouve sa place.

La documentation donne un nom à ce conflit de profondeur, le z-fighting, et l’assume avec humour. C’est même l’un des « charmes » de Zdog, écrit-elle, avant d’inviter à l’accepter. Elle propose aussi une parade, le Group, qui dessine ses formes dans l’ordre où on les ajoute. C’est ce qu’utilise notre bol de ramen, vu sous un angle fixe.
Le reste de la liste est court mais net. Pas de texture, pas d’import de modèles : tout se construit en code. L’import de tracés SVG, réclamé depuis mai 2019 et soutenu par 125 votes, attend toujours. Et plus les formes s’accumulent, plus le dessin ralentit, comme le montre notre banc d’essai.
Canvas ou SVG ? Notre banc d’essai
On a fait tourner un nuage de sphères, de 50 à 3 200 formes, sur deux tailles d’image. À chaque fois, on a mesuré le temps pour calculer et afficher une image, dans un Chromium sans carte graphique.
Le Canvas l’emporte partout, de 1,5 à 3,3 fois plus vite. La barre à surveiller, c’est 16,7 millisecondes par image, soit 60 images par seconde. Sur une image de 500 pixels de côté, le Canvas reste dessous jusqu’à 3 200 formes. Le SVG la franchit entre 1 600 et 3 200 formes. Sur une image de 1 500 pixels, le Canvas décroche entre 1 600 et 3 200 formes. Le SVG, lui, lâche prise entre 400 et 800.
La documentation conseille d’ailleurs le Canvas pour les scènes chargées, et l’explique par le DOM. En SVG, chaque forme est un élément de la page, à dessiner et à trier. À chaque image, Zdog vide le SVG, puis y réinsère chaque forme dans l’ordre de profondeur. Notre banc chronomètre ce manège. À 3 200 formes, il coûte 14 à 17 millisecondes de JavaScript, environ quatre fois plus qu’en Canvas.
Le Canvas, lui, peint des pixels, et paie la taille de l’image. À 3 200 formes, son temps par image est multiplié par 2,6 entre 500 et 1 500 pixels de côté. Celui du SVG, par 1,4. D’où le conseil de la doc : le SVG pour peu de formes sur une grande image. Chez nous, l’écart se resserre bien, mais le SVG ne passe jamais devant.
Pour quelques dizaines de formes, la vitesse ne départage rien : moins de 7 millisecondes dans tous les cas. Le SVG garde alors deux atouts. Il reste net à toutes les tailles. Et ses éléments de page, qui le ralentissent en masse, changent de camp. On peut les styler, ou enregistrer le tout en fichier .svg. Rendue en SVG, notre illustration de ramen ne diffère de la version Canvas que sur 0,06 % des pixels. Tous au bord des formes.
Zdog ou three.js ?
Pour la même boule qui tourne, empaquetée et compressée de la même façon, Zdog pèse 7,8 Kio. three.js en demande 129, et Babylon.js 332. Charger la bibliothèque entière creuse l’écart : 181 Kio pour three.js, plus de 1,8 Mio pour Babylon.js.
Ce poids achète de vraies capacités. Lumières, ombres, textures, perspective, modèles glTF exportés de Blender : three.js fait tout ce que Zdog ne fait pas. Il s’appuie pour cela sur WebGL et la carte graphique.
Le partage des rôles est donc simple. Zdog pour une illustration, un logo animé, une icône qu’on fait pivoter. Bref, quelques dizaines de formes au rendu doux et rond. three.js dès qu’il faut éclairer, texturer ou charger un modèle. Et pour monter une scène 3D web sans écrire de code, Spline fait le même travail à la souris.
Zdog est-il abandonné ?
Il n’évolue plus, c’est certain. La dernière version, la 1.1.3, a été publiée sur npm le 22 janvier 2022. Le README du projet annonce pourtant toujours « beaucoup de changements pour la v2 ». Cette v2 n’est jamais sortie, et le dépôt compte 46 tickets ouverts.
Mais Zdog ne s’appuie que sur des briques stables du navigateur, le Canvas 2D et le SVG. C’est pour ça qu’il tourne toujours, tel quel, près de cinq ans après sa dernière mise à jour. Sous licence MIT, rien n’empêche de copier le fichier sur ton propre serveur plutôt que de dépendre d’un CDN. Et ses 2 100 lignes se lisent en une soirée, si un jour il faut le corriger soi-même.
Un os à ronger pour se lancer
Copie le dango
Colle le code de cet article dans un fichier .html et ouvre-le. La brochette tourne, et la souris la fait pivoter.
Change de formes
Remplace les boules par Ellipse, Rect ou Hemisphere, et joue sur les réglages stroke et fill.
Bascule en SVG
Change la balise de départ et compare. Au-delà de quelques centaines de formes, reviens au Canvas.
Range ce qui se chevauche
Si une forme passe devant à tort, coupe-la en morceaux ou range-la dans un Group.
La documentation et les démos officielles attendent sur zzz.dog.
Soyez le premier à commenter cet article !