Afficher des images SVG dans canvas

Un script pour utiliser des formes prédéfinies (décrites en SVG) dans une surface canvas de HTML 5.

Il serait intéressant de disposer d'une bibliothèque d'images pour canvas, pas seulement des sprites, mais aussi des images vectorielles dont on puisse changer la tailler ou modifier les composants élémentaires, ou les recomposer pour produire de nouvelles images.

En utilisant le format SVG, on dispose d'un moyen de décrire ces images de façon simple et standard.

Le script que l'on a réalisé pour les afficher ne reprend pas des images faites avec un logiciel comme Inkscape, qui utilise SVG comme format de stockage, mais n'est pas conçu pour optimiser le code SVG. Vos images devraient être écrites en code source, mais un logiciel comme SVG Edit peut aussi fournir du vrai code SVG.

Un outil est inclu dans l'archive pour convertir les images svg en objets JavaScript. Ensuite la fonction SVGtoCanvas affiche l'image dans une balise canvas, à une vitesse incomparablement supérieure à celle de l'affichage SVG.

Exemple d'utilisation

SVG

Scriptol

Code source de l'image:

<svg id="car"  xmlns="http://www.w3.org/2000/svg"  width="400" height="200">
<g stroke="#000000" stroke-width="2" fillStyle="none">
<!-- Bodywork -->
<line x1="50" y1="40" x2="100" y2="40" />
<line x1="45" y1="35" x2="50" y2="40" />
<line x1="100" y1="40" x2="105" y2="35" />
<line x1="105" y1="35" x2="140" y2="35" />
<line x1="105" y1="35" x2="100" y2="15" />
<line x1="40" y1="60" x2="140" y2="60" />
<!-- Radiator -->
<rect x="140" y="35" width="5" height="25" fill="none" stroke-width="2" />
<!-- Wheels -->
<ellipse cx="30" cy="60" rx="15" ry="15" fill="black" />
<ellipse cx="30" cy="60" rx="12" ry="12" fill="white" />
<ellipse cx="30" cy="60" rx="4" ry="4" fill="gray" stroke-width="1" />
<ellipse cx="140" cy="60" rx="15" ry="15" fill="black" />
<ellipse cx="140" cy="60" rx="12" ry="12" fill="white" />
<ellipse cx="140" cy="60" rx="4" ry="4" fill="gray" stroke-width="1"/>
<!-- Trunk -->
<path d="M 45,35 C 35,35 20,35 10,50" fill="none"/>
<line x1="10" y1="50" x2="15" y2="60" />
<!-- Hood -->
<path d="M 45,35 C 30,10 35,10 100,15" fill="none" stroke-width="2"/>
<path d="M 55,40 C 50,15 35,15 100,15" fill="none" stroke-width="2"/>
<!-- Glass separator-->
<line x1="75" y1="40" x2="70" y2="15" />
<!-- Ad -->
<text x="60" y="53" font-size="14">Scriptol</text>
</g>
</svg>

Canvas

Code source JavaScript:

<canvas id="solcar" width="400" height="100"></canvas>

<script src="code/scriptolcanvas.js"></script>
<script src="car.js"></script>

<script>
 var ctx = canvasInit("solcar")
SVGtoCanvas(car, ctx, 0, 0) </script>

Auparavant nous avons produit le fichier car.js à partir de car.svg avec le script svgtojs.js

Comment l'image s'affiche dans la balise canvas

Voici le code source de la fonction SVGtoCanvas:

function SVGtoCanvas(el, ctx, xo, yo) {
    var tag 
    var x, x2, y, y2, cx, cy, rx, ry, w, h
    var data, font, arr, path
    var fillFlag=false
    ctx.save()  
    ctx.beginPath()  
    for(var att in el) {
       var val = el[att]
       switch(att) {
       case 'tag':
            tag = val
            break
       case 'data':
            data = val            
       case 'stroke':
            ctx.strokeStyle=val
            break
       case 'stroke-width':
            ctx.lineWidth=val
            break
       case 'fillStyle':
       case 'fill':
            if(val=="none") val="transparent"
            ctx.fillStyle=val
            fillFlag=true
            break                
       case 'x':
       case 'x1':
            x = Number(val) + xo
            break
      ... etc...
      } 
    }
    switch(tag) {
        case 'line':
            ctx.moveTo(x,y)
            ctx.lineTo(x2,y2)
            ctx.stroke()
            break;
        case 'circle':
            ctx.arc(cx, cy, rx, 0, 2 * Math.PI);
            ctx.stroke();                
            break;
       ... etc...
   }
   ctx.restore()        
}

Le code complet est dans l'archive à télécharger.
Tous les compilateurs savent optimiser les structures switch ... case, ce qui fait que l'affichage de l'image est extrêmement rapide.

Les commandes de l'API canvas ne sont pas encore toutes implémentées, c'est pourquoi le code est mis en ligne sur GitHub: il est facile de le compléter et partager les modifications si besoin.

Voir aussi: Convertir SVG en JSON.