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
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.