Comparaison entre SVG et Canvas

Différences

Pour dessiner (voire créer une animation graphique) directement dans une page web vous avez le choix entre deux technologies : SVG ou Canvas.

Laquellle retenir ?

La première différence entre ces deux technologies tient aux types de données manipulées. SVG est un format vectoriel tandis que Canvas est un format matriciel (bitmap). On a donc d’un côté, des formes définies à l’aide de points et de courbes, et de l’autre un "bouillon" de pixels.

Une autre différence de fond entre ces deux technologies tient à la façon de les utiliser. SVG est un langage qui repose sur une syntaxe XML, il est dit déclaratif. Vous dites explicitement au navigateur ce qu’il doit dessiner.
Canvas lui, repose sur une API (du JavaScript) : vous allez devoir programmer la façon dont le navigateur va devoir dessiner. On dit que Canvas est procédural.

SVG reposant sur une syntaxe XML, son interprétation par un navigateur conduit à la construction d’un arbre DOM qui comprendra l’ensemble des objets constitutifs de l'image. De son côté un dessin produit par Canvas n'est pas repris dans l'arbre DOM.
Pour parler plus simple chaque objet SVG pourra être manipulé avec JavaScript (ou CSS) en tant qu'élément du DOM alors que les objets Canvas ne sont pas des "noeuds" du DOM.

Points communs

Les deux technologies sont compatibles avec le "responsive web design".
Que ce soit avec SVG ou avec Canvas il est possible d'exprimer la largeur des zones de dessin en % de l'écran à condition de créer à côté un système de coordonnées indépendant de la taille effective du canevas.
Voir plus bas les explications au travers d'un exemple.

Combiner les deux outils

Rien n'interdit de superposer une zone de dessin SVG sur un canevas Canvas ou vice-versa ...

Exemple

Ci-dessous deux bandeaux : le premier produit avec SVG et le second avec Canvas

Le code de la solution SVG

... <body> <svg width = '80%' height = 'auto' style = 'background : lime; ' viewBox ="0 0 800 100" > <symbol id = 'maison'> <!--cheminee puis toit puis murs puis porte et fenêtres--> <rect x ='60' y = '10' width = '10' height = '40' fill = 'yellow'/> <circle cx = '50' cy = '50' r="30" fill = 'red' /> <rect x = '20' y = '50' height ='30' width = '60' fill = 'yellow' /> <rect x = '30' y = '60' height ='10' width = '10' fill = 'black' /> <rect x = '50' y = '60' height ='20' width = '10' fill = 'black' /> <rect x = '65' y = '60' height ='10' width = '10' fill = 'black' /> </symbol> <use xlink:href="#maison" width ="100" height="100" x="0" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="100" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="200" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="300" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="400" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="500" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="600" y="0" /> <use xlink:href="#maison" width ="100" height="100" x="700" y="0" /> </svg> ... </body>

Le code de la solution Canvas

... <body> ... <canvas width = '800' height ='100' style = 'width : 80% ; height : auto ; background : lime; '></canvas> ... <script> var canevas = document.querySelector('canvas'); var contexte = canevas.getContext('2d'); var X = canevas.width ; var Y = canevas.height ; for (i =1; i<=8 ; i++) { contexte.fillStyle ='yellow'; contexte.fillRect(60,10,10,40); // cheminee contexte.fillRect(20,50,60,30); // mur contexte.fillStyle = 'red' ; contexte.arc(50, 50, 30, Math.PI, Math.PI*2); //toiture contexte.fill() ; // colorier toiture contexte.fillStyle = 'black'; // changement couleur de remplissage contexte.fillRect(30,60,10,10); contexte.fillRect(50,60,10,20); contexte.fillRect(65,60,10,10); contexte.translate(100,0) ; // déplacement du point d'origine } // fin for </script> ...

Commentaire

Les deux zones de dessin SVG et Canvas s'adaptent à la taille de l'écran (largeur = 80% de celle du conteneur dans les deux cas).

En SVG on définit un modèle : formes contenues dans la balise SYMBOL ; on identifie ce modèle "maison" ; on "clone" ce modèle 8 fois (emploi de la balise USE) mais avec un positionnement différent à chaque fois.

En Canvas on crée une boucle qui est exécutée 8 fois et à chaque passage dans la boucle on redessine les formes constitutives d'une maison puis on effectue un changement d'origine grâce à la méthode translate.
Retour menu