Chez Jérémie

Chez Jérémie, parfois c'est sérieux, parfois non !

Introduction à SVG

- Web - Lien permanent

Dans les années à venir, le format d'image SVG (Scalable Vector Graphics) va devenir une technologie extrêmement commune sur le Web. Le décollage de cette technologie va se faire grâce à deux évènements d'importance dans le monde du Web. D'une part, avec l'arrivée du support de SVG par Internet Explorer 9, cette technologie sera désormais disponible nativement dans tous les navigateurs majeurs du marché. D'autre part, la norme HTML 5 va normaliser et simplifier la façon d'embarquer du SVG directement au sein des documents HTML. C'est le moment ou jamais de s'intéresser à cette technologie ;)

C'est quoi SVG ?

SVG est un format d'image vectoriel reposant sur une syntaxe XML. Dit comme ça, c'est sûr, ça n'est pas très sexy ! En fait, ce format d'image est un peu le meilleur de deux mondes :

  • D'un coté, c'est un format d'image vectoriel. C'est à dire que, contrairement à une image bitmap (on dit aussi "matricielle" ou parfois "rastérisée"),  les images créées avec ce langage peuvent être agrandies et manipulées sans perte de qualité.
  • D'un autre coté, elle sont définies à l'aide d'une syntaxe XML.

Ce dernier point a trois avantages :

  • Le code source des images reste théoriquement humainement lisible (mais ne rêvons pas trop tout de même, hein).
  • Une image SVG peut être transformée en arbre DOM, ce qui permet de la manipuler facilement avec des langages tel que Javascript.
  • Il est possible de rendre le contenu de ces images accessible sans recourir à des artifices de substitution ou de contenus alternatifs (par exemple, le texte reste compréhensible comme tel et peut donc être sérialisé pour un lecteur d'écran).

En tant que format d'image, SVG est très riche. En effet, il ne se contente pas de fournir un outillage complet de dessin mais offre également toutes une série de fonctionnalités permettant d'animer et transformer une image sans avoir besoin de recourir à des technologies tiers. Ceux d'entre vous qui ont connu Flash à l'époque où il s'agissait encore d'un simple système d'animation vont retrouver des concepts connus :)

Comment l'utiliser

Structure de base d'un document SVG

SVG étant un document XML, il suit cette syntaxe :

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100" height="100" version="1.1"
 xmlns="http://www.w3.org/2000/svg">

    <circle cx="50" cy="50" r="40" style="fill:#000"/>

</svg>

> L'exemple du document SVG dans votre navigateur

Dans cet exemple on retrouve donc le prologue XML, une déclaration de DTD, l'ouverture d'un balise racine (la balise svg) qui contiendra l'ensemble des balises qui définiront votre image. Pour ceux d'entre vous qui ont l'habitude de HTML mais pas spécialement de XML, notez la présence de l'attribut standalone avec la valeur no dans le prologue XML. Pour faire simple, il permet de dire aux parseurs XML qui vont traiter le document qu'il peut y avoir autre chose que du SVG dans votre document. En effet, les documents SVG utilisent d'autres espace de nom (Xlink pour les liens vers des ressources externes) et peuvent facilement embarquer d'autres langages XML (MathML, XHTML, etc.) via la balise foreignObject.

Si vous avez l'habitude du HTML mais n'avez encore jamais manipulé de document XML, vous devez garder à l'esprit que la syntaxe d'un document XML est beaucoup plus rigoureuse : le respect de la casse est obligatoire, les balises doivent être impérativement fermées, etc. Ceci étant, si vous faites une erreur, vous le saurez vite. En effet, les parseurs XML ne sont pas connus pour leur permissivité, au contraire !

Embarquer un document SVG dans une page HTML

Certes, vous pouvez afficher un document SVG dans votre navigateur préféré (pour IE, il faudra attendre la version 9) mais là ou ça devient intéressant c'est quand on peut le mettre directement dans une page HTML (et le manipuler avec Javascript et le créer à la volée et vous voyez quoi...).

L'utilisation directe de balises SVG dans le code HTML

Cette méthode, c'est le graal en ce qui concerne l'utilisation de SVG. L'idée, c'est de pouvoir mettre n'importe où dans un document HTML une balise svg qui contiendra d'autres balises du langage SVG. Autant dire que ça va simplifier grandement les choses. 

Vous ne rêvez pas car c'est ce que propose la norme HTML 5. Par contre, pas de bol, ce n'est implémenté dans aucun des navigateurs du marché pour l'instant... enfin presque. En effet, actuellement Firefox permet l'inclusion directe de SVG au sein d'un document XHTML. La nuance est importante car cela signifie que vos pages XHTML doivent êtres servies avec le bon type mime par le serveur et que le document sera analysé à l'aide d'un parseur XML et non pas HTML (en gros permissivité 0, au moindre truc de travers, la page ne sera pas affichée ou alors avec un gros message qui fait peur... vraiment !).

Dans Firefox, ça donne ça :

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg-flat.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Exemple de tags SVG dans un document en XHTML</title>
</head>
<body>

<svg:svg xmlns:svg="http://www.w3.org/2000/svg" width="100" height="100" version="1.1">

    <svg:circle cx="50" cy="50" r="50" style="fill:#000"/>

</svg:svg>

</body>

> Voir l'exemple XHTML

Dans le future Firefox 4 (prévus pour fin 2010, début 2011) ainsi que dans IE 9, il sera possible d'embarquer du SVG dans un document HTML 5 sans avoir à se préoccuper de la gestion des espaces de nom. Vous pouvez d'ailleurs déjà tester cette fonctionnalité dans les "nightly build" de Firefox 3.7/4 ou avec la version de test du moteur de IE9. Cela permettra de réaliser ce type de document :

<!DOCTYPE html>

<html>
<head>
   <title>Exemple de tags SVG dans un document en HTML 5</title>
</head>
<body>

<svg width="100" height="100">

    <circle cx="50" cy="50" r="50" style="fill:#000"/>

</svg>

</body>

> Voir l'exemple HTML

SVG c'est un format d'image, alors pourquoi pas la balise img ?

Dans la mesure où SVG est un format d'image, on peut légitimement penser pouvoir utiliser la balise img pour inclure ce type de document :

<img src="cercle.svg" alt="" />

> Voir l'inclusion via img

Néanmoins, utiliser SVG de cette manière n'est pas trivial. Par exemple, il est possible d'embarquer des langages de scripts dans un document SVG. Or, qui dit langage de script, dit problème de sécurité et la balise img n'a pas été conçue à la base pour traiter ce genre de question. De même, déterminer la taille par défaut en pixel d'une image vectorielle peut parfois être un peu délicat. Ceci dit, les constructeurs de navigateurs y travaillent dur :

Et avec CSS aussi pourquoi pas !

Le support de SVG comme une source d'image dans CSS ouvre des perspectives inimaginables jusqu'à présent. En particulier, comme SVG est un format vectoriel qui supporte parfaitement l'agrandissement et la réduction, cela permettra de créer des arrières plans extensibles sans perte de qualité. Ainsi, écrire quelque chose comme ça, ne posera plus aucun problème :

div{
    width : 50%;

    background-image : url(cercle.svg);
    background-size : cover; /* Propriété CSS 3 qui permet de redimensionner l'image d'arrière plan à la taille de son conteneur */
}

> Voir l'inclusion via CSS

On peut même aller jusqu'à imaginer des arrières plans animés (attention à l'accessibilité quand même) en mixant SVG et la balise HTML 5 video. Bref, en utilisant conjointement ces 3 technologies, on peut vraiment faire beaucoup de choses.

La problématique d'implémentation est la même qu'avec la balise img, et le support navigateurs est le même.

L'utilisation de la balise object

La balise object est faite pour embarquer à peu près n'importe quoi dans une page Web. Historiquement, cette méthode est utilisée pour SVG car il est possible de faire appel à un plugin tiers pour afficher un document SVG. Cette nécessité disparaît avec les navigateurs qui supportent nativement ce format d'image. Vous pouvez néanmoins toujours utiliser cette façon d'embarquer du SVG. Le gros avantage de cette méthode, c'est que vous pouvez gérer très facilement l'alternative HTML à fournir en cas d'absence du support de SVG

<object type="image/svg+xml" data="cercle.svg">
    <img src="cercle.png" alt="Votre navigateur ne supporte pas le format SVG !" />
</object>

> Voir l'inclusion via object

Quand tout le reste a échoué, il reste les iframe !

Si vous utilisez un navigateur qui comprend SVG mais qui ne comprend aucune des autres méthodes vues ci-avant (!!), vous avez toujours la possibilité d'utiliser une iframe... avec tous les problèmes inhérents à une gestion de frame. Franchement, si je vous parle de cette méthode ici, c'est par honnêteté intellectuelle, mais je vous encourage à considérer cette méthode comme la technique de "la dernière chance".

> Voir l'inclusion via iframe

Qu'est-ce qu'on peut faire avec ce langage ?

Maintenant que je vous ai montré comment utiliser SVG dans vos documents HTML, on peut se concentrer sur son utilité réelle :)

Dessin

SVG étant avant tout un format d'image vectoriel, vous pouvez donc dessiner des formes : Des formes simples comme des lignes (lignes droites avec line ou lignes brisées avec polyline), des polyèdres (des rectangles ou carrés avec rect ou des polygones avec polygon), des ellipses (des cercles avec circle ou des ellipses arbitraires avec ellipse) ou des formes totalement arbitraires avec la balises path.

Il est possible d'appliquer des styles CSS à ces formes (via la balise style). SVG enrichie les propriétés issues de la norme CSS 2 avec des propriétés qui lui sont propre, en particulier pour gérer le style des lignes (propriétés stroke-*) et du remplissage des formes (propriétés fill-*)

On peut également embarquer des images bitmap dans un document SVG (via la balise image)

Enfin, tous ces éléments peuvent être groupés entre eux pour constituer des ensembles de formes cohérents (et donc plus facile à manipuler de manière globale) en utilisant la balise g et vous pouvez les dupliquer et les réutiliser à l'infini avec la balise use.

Filtres et transformation

Transformations

Un des grands intérêts des formes vectorielles, c'est qu'il est possible d'y appliquer des transformations sans perte de qualité. En effet, un tracé vectoriel est défini par un certain nombre de points clés dans un espace de coordonnées (contrairement aux images bitmap qui définissent tous les points du tracé de manière exhaustive et absolue). Il est donc très facile de déplacer ces points dans cet espace de coordonnées via de "simples" transformations mathématiques.

En SVG les transformations s'appliquent via l'attribut transform utilisable par toutes les balises. On peut appliquer autant de propriétés de transformations que l'on veut à un tracé, il suffit de séparer chacune d'elles par une virgule ou un espace. Vous avez à disposition, soit des transformations simples : déplacements (propriété tranlate), rotations (propriété rotate), déformations (changement d'échelle avec scale et inclinaison avec skewX et skewY) ; soit des transformation matricielles arbitraires (via la propriété matrix).

Par exemple, si vous voulez créer un losange, dessinez un carré et appliquez lui une rotation de 45° et une déformation verticalle :

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100" height="100" version="1.1"
xmlns="http://www.w3.org/2000/svg">

    <rect x="25" y="25" width="50" height="50"
          transform="translate(50 12.5) scale(1 0.5) rotate(45)" />

</svg>

> Les transformations en action

Dans l'exemple précédent, notez que les transformation s'appliquent de la droite vers la gauche (d'abord la rotation, puis le changement d'échelle puis le déplacement). La transformation translate supplémentaire permet de replacer le losange au centre de la zone de dessin. Je ne vous détaillerai pas ici la gestion du système de coordonnées dans SVG, c'est assez compliqué et nécessiterait un article à part entière. Souvenez vous juste que c'est un point auquel vous devrez porter beaucoup d'attention dès que vous allez vouloir jouer avec les transformations.

Filtres

Les filtres sont un mécanisme qui permet d'appliquer des effets spéciaux à tout ou partie d'un document SVG. En effet, dans le cadre d'un dessin vectoriel, les courbes et les formes ne font pas tout. Les filtres permettent de créer des effets de flou (feGaussianBlur), de lumière (feSpecularLighting, feDiffuseLighting, etc.), de mélange d'image (feBlend, feComposite, etc.), d'application de texture (feTurbulence), etc.

Ces effets de bases peuvent êtres combinés au sein de la balise filter et chaînés entre eux pour créer des filtres complexes. Une fois un filtre défini, il est appliqué à un élément grâce à l'attribut filter. Oui, vous avez bien lu, il y a une balise ET un attribut filter. Plutôt qu'une explication fastidieuse, voici un exemple ou un simple cercle noir est mis en relief :

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="100" height="100">

    <defs>
        <filter id="MonFiltre" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="120">
            <!-- On floute l'objet source -->
            <feGaussianBlur in="SourceAlpha" stdDeviation="5" result="flou"/>
            <!-- On décale le résultat du flou qu'on appellera "Ombre" -->
            <feOffset in="flou" dx="3" dy="3" result="Ombre"/>
           
            <!-- On crée une source de lumière spéculaire avec un point d'éclairage en haut à gauche -->
            <feSpecularLighting in="flou" surfaceScale="10" specularConstant=".75"
                                specularExponent="1" lighting-color="#EFEFEF" 
                                result="speculaireSortie">
                <fePointLight x="-5000" y="-10000" z="2000"/>
            </feSpecularLighting>
           
            <!-- on applique la source de lumière à l'objet source -->
            <feComposite in="speculaireSortie" in2="SourceAlpha" operator="in" result="speculaireSortie"/>
            <!-- On mélange le résultat de la lumière sur l'objet source avec l'objet source lui même -->
            <feComposite in="SourceGraphic" in2="speculaireSortie" operator="arithmetic"
                         k1="0" k2="1" k3="1" k4="0" result="SourceEclairee"/>

            <!-- On empile l'objet éclairé avec son ombre pour obtenir le résultat final -->
            <feMerge>
                <!-- d'abord l'ombre... -->
                <feMergeNode in="Ombre"/>
                <!-- ...puis l'objet éclairé par dessus -->
                <feMergeNode in="SourceEclairee"/>
            </feMerge>
        </filter>
    </defs>

    <!-- le filtre est appliqué au cercle qui gagne une ombre et prend du volume -->
    <circle style="fill:#000" filter="url(#MonFiltre)" cx="50" cy="50" r="40"/>
</svg>

> Les filtres en action

Animation, Scripting et gestion évènementielle

Dessiner, c'est bien. Rendre interactif, c'est mieux, surtout quand on parle de Web ;)

SVG étant un format XML, il est possible de le manipuler via le DOM. L'accès au DOM se fait via un langage de scripting. Dans la plus part des cas, c'est le Javascript qui est utilisé (sa version normalisé ECMAScript pour être exact qui est le langage utilisé par défaut dans la norme SVG), mais rien n'empêche d'imaginer utiliser d'autres langages comme Pyton ou VBScript par exemple. En fait cela dépend du logiciel que vous utiliserez pour visionner votre document SVG or dans un navigateur, assez naturellement, on se tournera vers Javascript. L'ajout de script se fait comme en HTML via la balise script.

SVG se conforme à la norme DOM pour la gestion des évènements, mais comme pour les styles CSS, il l'enrichie de certains évènements qui lui son propre. Par exemple, SVGZoom qui permet de savoir quand un changement de taille d'image à lieu ou SVGScroll qui permet de savoir quand est-ce qu'une vue d'un document est déplacée au sein même de la zone d'affichage du document SVG.

Enfin, dernier point important, il est possible d'animer des objets SVG de manière déclarative (sans utiliser de langage de script). Pour cela, SVG se repose sur un autre langage, le SMIL. Là encore, un bon exemple valant mieux qu'un long discours, voila un exemple où une flèche tourne en rond en suivant un tracé (oui, j'aurai pu faire un truc plus sexy, mais au moins ça reste compréhensible) :

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="200" height="200"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
   
    <defs>
        <!-- On définie le tracé du mouvement : un cercle mais sans utiliser la balise circle -->
        <path id="trace" d="M100,50 a50,50 0 1,0 1,0 z" />
    </defs>

    <!-- On dessine le contour du tracé de mouvement en réutilisant le tracé. -->
    <use xlink:href="#trace" fill="none" stroke="grey" stroke-width="1px" />

    <!-- Voici un triangle qui se déplacera sur le tracé de mouvement. -->
    <path d="m0,0 l0,6 l20,-6 l-20,-6 z"
          fill="yellow" stroke="red" stroke-width="2px"  >

        <!-- Définition de l'animation sur le tracé de mouvement -->
        <animateMotion dur="6s" rotate="auto" repeatCount="indefinite">
            <mpath xlink:href="#trace" />
        </animateMotion>
    </path>
</svg>

> Voir l'animation en action

Des logiciels pour se simplifier la vie

Même s'il n'est pas très compliqué d'éditer un document SVG à la main, il vous faudra passer par des logiciels d'édition SVG si vous voulez faire des choses vraiment sexy au niveau design. Les principaux logiciels de dessin vectoriel du marché permettent à minima de produire des dessins statiques au format SVG. Par contre il est assez difficile de trouver des logiciels permettant d'exploiter les fonctions avancées de SVG comme l'animation ou l'interactivité via des scripts (à mon avis, c'est sans doute le principal frein à un déploiement massif de SVG). D'ailleurs sur ce point, si on compare à Flash... il n'existe pas d'équivalent au Adobe Flash IDE pour travailler avec SVG.

  • Inkscape
    Il s'agit d'un éditeur de dessin vectoriel libre et gratuit. Le SVG produit est de bonne qualité, même s'il faut un peu se méfier des options d'enregistrement si on  veut éviter une soupe de tag un peu indigeste. Les filtres sont relativement bien supportés (l'éditeur de filtres est assez intuitif). Par contre, il ne gère pas (encore) les animations ni le scripting. Il a l'ambition de supporter l'intégralité de la norme SVG 1.1 pour la sortie de sa version 1 (mais on n'y est pas encore).
  • Adobe Illustrator
    Un des logiciels historique de Adobe. Sa qualité en temps qu'éditeur vectoriel n'est plus à faire. L'exportation en SVG est d'excellente qualité. Les filtres sont parfaitement supportés mais leur édition est franchement mauvaise (édition en mode texte). Cela tiens au fait que Illustrator n'utilise pas SVG comme format natif et qu'il ne fait que de l'import/export à ce format. Ainsi, si vous utilisez certaines fonctionnalités ou filtres spécifiques à Illustrator, vous risquez d'avoir quelques surprises. Prenez le temps d'expérimenter. Il ne gère ni le scripting ni les animations.
  • Aviary.com (Raven)
    La suite d'outils en ligne du site aviary.com propose un éditeur vectoriel appelé Raven. Cette éditeur exclusivement en ligne est assez frustre et ne permet que de faire du dessin. Il ne supporte ni les filtres, ni le scripting, ni les animations.
  • Amaya
    Il s'agit de l'éditeur/navigateur développé par le W3C et l'INRIA. Il supporte la plupart des langages normalisés par le W3C, dont le SVG. Bien que son ergonomie soit douteuse à mon sens, c'est un des très rare (si ce n'est le seul) éditeur SVG qui gère les animations déclaratives.

Il existe également un certains nombre de bibliothèques Javascript qui offrent un haut degré d'abstraction, comme par exemple RaphaelJS ou SVGWeb, pour créer et manipuler un documents SVG plus facilement qu'en utilisant directement les fonctions DOM. Elles permettent souvent de contourner les limites des différents navigateurs (en simulant le support de SVG dans IE ou en rajoutant le support des animations dans Firefox 3.6 par exemple).

Conclusion

Voila pour un petit tour d'horizon rapide de cette technologie. Le couple SVG / HTML5 offre des opportunités graphiques sans précédent dans le web standard. Comme toutes les technologies web, SVG n'est pas très compliqué au premier abord mais regorge de subtilités dès qu'on se met à creuser. Prenez le temps de vous familiariser avec, vous ne devriez pas le regretter :)

En savoir plus