Petit mémo sur le format SVG
Attention: cet article date du 30 août 2012
Ce qu'il contient est peut être encore valable...
... ou complètement obsolète!
Dans les formats disponibles pour des images ou schémas, nous pouvons utiliser les classiques GIF, JPG et PNG. Chacun ayant avantages, inconvénients, et usages adaptés. Ils ont tous l’inconvénient d’être bitmaps, c’est à dire en mode point, et relativement difficiles à travailler au sein d’une page.
Le SVG (Scalable Vector Graphics (donc graphique vectoriel adaptable) étant vectoriel, il a l’avantage d’être adaptable, redimensionable avec de bonnes qualités, souvent léger, manipulable avec des feuilles de styles et du javascript…
L’intérêt de ces deux derniers points est à mon sens de pouvoir justement programmer le SVG, pour y intégrer du code, donc des mécanismes pouvant automatiser de nombreuses choses: changement d’état, interaction avec l’utilisateur, formules mathématiques, boucles pour répéter des motifs à bon compte, etc. En format bitmap, on retrouve la même logique avec le <canvas> du html5.
S. V. G. ?
Le SVG est donc un format vectoriel, mais surtout basé sur un standard: c’est du XML. Il se construit donc à partir de balises imbriquées, avec des attributs, des class, des styles, etc.
A quoi ça ressemble ? Prenons un exemple trivial (voir démo):
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <circle id="cerclerouge" cx="50" cy="50" r="40" fill="#FF0000" /> </svg>
Ici, nous construisons un svg carré, avec un cercle rouge à l’intérieur.
Ou mettre ce bout de code ? Simplement dans le DOM, c’est à dire au fil de votre page html, à l’endroit où vous avez besoin d’un cercle rouge…
Notons que l’attribut xmlns n’est utile qu’en xHtml, pas en html5. Et que si votre body possède un background, le svg étant transparent, on verra à travers (le rond sera donc rond…)
Comme il est partie intégrante du DOM, le SVG est utilisable comme n’importe quelle balise, donc avec feuille de style et javascript, par exemple avec des onclick, des rollover, etc.
Style: modifier l’aspect du SVG
Ajoutons quelques bordures, code à placer dans le header de notre page (voir démo):
<style> svg { border: 1px solid #000 } #cerclerouge { stroke: #006600; stroke-width: 4px; } </style>
Notez que si la balise svg est une balise html elle utilisera des attributs html (ici la bordure noire de 1px), mais que ce que le SVG contient utilisera des attributs propres au format. Ainsi stroke et stroke-width pour une belle(!) bordure verte de 4px…
Il est également possible d’utiliser des class, des feuilles de styles externes…
Javascript: interagir avec un SVG
Ici, je fais simple et pas forcément optimisé… (voir démo):
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <script type="text/javascript"> function changeCol(moiMeme) { var r = Math.round(Math.random()*255); var g = Math.round(Math.random()*255); var b = Math.round(Math.random()*255); moiMeme.setAttribute("fill","rgb(" + r + "," + g + "," + b + ")"); } </script> <circle id="cerclerouge" onclick="changeCol(this)" cx="50" cy="50" r="40" fill="#FF0000" /> </svg>
Pour que la magie opère, je vous invite à cliquer sur le cercle en question.
Notez que le code javascript est placé à l’intérieur de la balise <svg>, il aurait tout aussi bien pu être à l’extérieur dans le <head> de la page, voir un fichier externe.
Et que les amateurs de jQuery seront à la fête, ça marche également.
Javascript: programmer un SVG
Ici encore, je fais simple et pas forcément optimisé… (voir démo):
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <script type="text/javascript"> for (var i=4; i>0; i--) { var r = 10*i; document.write('<circle r="' + r + '" fill="#F00" cx="50" cy="50" />'); } </script> </svg>
Pour le coup, c’est le code qui crée des cercles concentriques grâce à la boucle. En l’état, impossible à mettre à l’extérieur du svg.
Bien sûr, tout est possible, y compris l’usage de formules mathématiques complexes, d’animations, etc.
Intégrer un SVG externe…
C’est en fait là où je voulais en venir au départ, à savoir comment placer un fichier SVG externe, par exemple pour l’utiliser sur plusieurs pages, ou qui serait un peu long et noierait votre page de code peu lisible. Le fichier externe ayannt également l’avantage de la mise en cache.
Plusieurs solutions s’offrent à nous, outre l’incorporation du SVG directement dans le DOM vue précédemment.
Object
<object type="image/svg+xml" data="fichier.svg"></object>
On peut glisser un affichage alternatif entre les balises (par exemple une version bitmap), et préciser des dimensions à la balise object.
Elle offre également des mécanismes de gestion en cas d’erreur dans l’affichage, ce qui en fait la syntaxe la plus adaptée à mon sens.
Embed
<embed data="fichier.svg" />
Il ne faisait parti d’aucune norme, mais était utilisé depuis longtemps, l’embed a donc été ajouté au html5.
Son inconvénient majeur étant de ne pas fournir de mécanisme d’erreur en cas de problème (ce que Object fait).
IFrame
<iframe src="fichier.svg"></iframe>
Les iframes ont été retirées des normes HTML 4 et XHTML, mais sont de retour en html5. Avec un rôle précis, celui d’y placer des contenus potentiellement dangereux (souvent extérieurs au site).
A déconseiller à mon sens, car ajoute de nombreuses complications (que je vous laisse cherche, na!).
Img
<img src="fichier.svg" alt="description alternative" />
Cela aurait pu être le format le plus adapté… et cela fonctionne (du moins sur la plupart des navigateurs).
Sauf qu’il faut oublier si vous y glissez des scripts, ou une quelconque interaction, si ce n’est un comportement comparable à une image (un rollover par exemple, dont on changerait le src). Une version statique du SVG en quelque sorte (logique, puisque img correspond à une image, pas une animation). Mais intéressant bien sûr si votre svg est… statique. Par exemple généré par un PHP pour faire un histogramme de données issues d’une base Mysql…
C’est également le seul a pouvoir avoir une balise <a> qui l’entoure si l’on veut le rendre cliquable dans un lien (mais on peut utiliser la balise <a> à l’intérieur du svg, pour encadrer quelques éléments précis…)
CSS
body { background-image: url('background.svg'); }
Bonne chose, on peut l’utiliser dans un background css. Sauf que ça ne fonctionnera pas avec certains navigateurs, ou avec des problèmes… et en version statique, avec les mêmes limitations que l’img vu ci dessous.
Conclusion
SVG est un format intéressant sous bien des aspects.
Le fait de pouvoir le créer en quelques lignes de code présente de nombreux avantages, comme par exemple l’utiliser pour une interaction avec du Javascript.
S’il est supporté par de nombreux navigateurs, il posera soucis avec les plus anciens (avant IE8, utiliser un plugin). Comme d’habitude et beaucoup d’autres balises ou format. Notons que c’est le format retenu pour Google Map ou Bing Map…
Je n’en ai pas parlé, mais un fichier SVG peut être créé par un outil de dessin vectoriel, comme illustrator ou inkscape (libre et gratuit) qui permettent tout de même des illustrations plus complexes que de simples rectangles… Attention, les fichiers ainsi générés sont bavards et ajoutent moults informations non forcément utiles pour l’affichage (plutôt en cas de modification) qui alourdissent votre fichier. Inkscape propose de sauvegarder au format SVG Simple, qui retire beaucoup.
Dans le même ordre, n’hésitez pas à réduire le nombre de points (Ctrl+L dans inkscape) si la qualité ne s’en ressent pas trop, vous gagnerez en poids. N’hésitez pas non plus à jeter un oeil dans le mode contour (Affichage > Mode > contour dans inkscape) qui fera apparaître des objets cachés, type blanc sur fond blanc, que vous pourriez vouloir supprimer.