Comparaison entre SVG et Canvas

Points communs et 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 image produite par SVG ne perdra pas en qualité si elle est agrandie alors qu'une image créée par Canvas et agrandie deviendra disgracieuse en particulier au niveau des courbes.

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 en tant qu'élément du DOM alors que les formes et chemins d'un dessin Canvas ne sont pas des noeuds du DOM.

Exemple

Ci-dessous deux images : la première produite avec SVG et la seconde avec Canvas

Zoomez la page (zoom avant) vous verrez alors que la première image (image vectorielle créée par SVG) reste parfaitement nette alors que la deuxième image (image matricielle produite par Canvas) devient disgracieuse

Le code de la solution SVG

... <body> <svg width = '90%' 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 = '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

En SVG comme en Canvas on utilise le CSS pour donner une couleur de fond à la zone de dessin. Ce pourrait être une image de fond ou un dégradé ...

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.

La zone de dessin SVG est adaptative (largeur exprimée en pourcentage) alors que la zone de dessin CANVAS ne l'est pas (largeur 800px).
En effet exprimer la largeur de la balise Canvas est possible à condition de le faire via CSS et alors les paramètres des méthodes de dessin doivent être des fraction de X et Y qui représentent respectivement les largeur et hauteur de la boîte CANVAS. Retour menu