SVGround : cours SVG

Structurer un document SVG

Jusqu’ici, notre code était très verbeux. Par exemple, même si plusieurs objets avaient les mêmes propriétés CSS, il fallait les écrire à chaque fois dans l’attribut style. De même, on ne pouvais pas réutiliser un carré déjà tracé pour le placer un peu plus loin et tourné. SVG bénéficiant des avantages de la syntaxe XML, il est facilement stylable avec CSS et fortement réutilisable grâce aux id. Au final, on peut très fortement optimiser un document SVG et lui faire adopter une structure logique qui facilitera toute modification du code.

De l’utilisation des CSS

SVG étant un langage XML, il est très facile de le styler avec CSS. Il existe quatre manière de styler un élément SVG :

Les attributs de présentation

Il existe tout un tas d’attributs de présentation pour styler un élément. Par exemple, pour avoir un carré rouge, on peut écrire :

< Un carré rouge ]]>

On peut aussi utiliser stroke, stroke-width, fill-opacity, etc. Cependant, on oubliera vite ce mode de styling parcequ’il ne respecte pas la règle de séparation des données et de la présentation, allourdit le fichier, et tout simplement ne permet pas de profiter des avantages des CSS.

Le style en ligne

C’est grâce au style en ligne que nous avons stylé nos dessin jusqu’à maintenant. En effet, les balises SVG acceptent toutes l’attribut style dans lequel on spécifie les couples propriété/valeur séparés par des point-virgules.

La feuille de style interne

À l’instar d’XHTML, SVG permet d’inclure une feuille de style interne grâce à la balise style placée comme premier enfant d’une balise SVG. On prendra le soin de placer tout cela dans une section CDATA, pour ne pas s’embêter avec les ', ", &, < et >. On devra aussi préciser que le style est du css, grâce à l’attribut type que nous fixerons à text/css qui est le type MIME de CSS.

Les sections CDATA font parti de la syntaxe de base de XML (1.0). Elles permettent d’éviter à l’auteur de devoir échapper les caractères spéciaux XML. Par exemple, ceci créera une erreur car 10 < 20 est considéré comme un début de balise :
<p>Hey les gars, 10 est inférieur à 20 ! En langage mathématique, on note 10 < 20 !</p>
On peut facilement échapper le texte en grâce à une section CDATA comme ceci :
<p><![CDATA[Hey les gars, 10 est inférieur à 20 ! En langage mathématique, on note 10 < 20 !]]></p>
Une section CDATA ne peut pas contenir la chaîne « ]]> ».

Par exemple, pour un même carré rouge :

< Un carré rouge

Toutes les balises XML peuvent avoir les attributs id et class. En CSS, on désigne un id par le croisillon (#) et la classe par le point (.). Par exemple, circle#cadran désigne le cercle dont l’id est cadran et .red_stroke désigne tous les éléments qui ont un attribut class qui vaut red_stroke.

Avoir une feuille de style interne est très pratique car elle permet de styler facilement toute sorte d’éléments. Vous souvenez vous de notre première forme ? C’était un rectangle noir. Noir parceque par défaut, une forme est remplie en noir. CSS nous permet de fixer d’autres valeurs par défaut. Si, par exemple, on veut que toutes nos formes soient par défaut non remplies et avec une bordure violette de 3 pixels, on fera :

< Redéfinition des styles par défaut avec CSS
Redéfinition des styles par défaut avec CSS

Le signe étoile (*) désigne, en CSS, tous les éléments présents. *{display:none;} n’affichera rien.

En général, on place style en début de page. On peut aussi préciser le média associé, grâce à l’attribut media qui peut prendre les valeurs suivantes :

Les types qui nous intéresserons principalement seront screen et print. Rien ne vous empêche d’avoir un élément style pour le média screen, un autre pour le média print, un troisième pour screen, etc.

Le seul inconvénient avec les feuilles de style internes, c’est qu’on ne peut pas proposer de feuilles de styles alternatives. Ce problème est résolu par l’utilisation de…

Feuilles de style externes

Pour utiliser des feuilles de style externes, il n’y a pas, comme en (X)HTML, de balise link : on doit donc utiliser la processing-instruction xml-stylesheet ….

La PI xml-stylesheet accepte 6 « attributs » :

Ces PI doivent être placées dans le prologue du document, c’est à dire juste après le prologue XML. On pourrait donc écrire :
xml-stylesheet href="doc.css" type="text/css" title="Feuille de style principale, pour tous les medias" charset="utf-8"
xml-stylesheet href="screen.css" type="text/css" title="Design clair" media="screen" charset="utf-8"
xml-stylesheet href="screen2.css" type="text/css" title="Design sombre" media="screen" charset="utf-8" alternate="yes"
xml-stylesheet href="print.css" type="text/css" title="Imprimer en couleurs claires" media="print" charset="Big5"
xml-stylesheet href="print2.css" type="text/css" title="Imprimer en couleurs sombres" media="print" charset="Big5" alternate="yes"
Cette PI est malheureusement encore mal implémentée, notamment au niveau de alternate.
Pour plus d’informations, lisez la spécification.

Dorénavant, on n’utilisera plus que cette méthode pour styler du SVG, tout simplement car c’est la méthode la plus flexible. Elle permet en outre de styler un nombre important de documents SVG grâce à un seul fichier. Reprenons notre carré rouge. Maintenant, on fera :

<]]> < Utilisation d’une feuille de style externe pour styler un carré ]]>

Et le CSS

Utilisation d’une feuille de style externe pour styler un carré

Dans cet exemple, les deux fichiers sont bien sur dans le même dossier. Lorsqu’on voudra changer la couleur de notre rectangle, il suffira de modifier le fichier CSS : on n’aura pas besoin de toucher à la structure du fichier XML, comme on l’aurait fait avec des attributs de présentation. Puissant, non ?

Une « astuce », que beaucoup ne connaissent pas, à propos de CSS : il est possible de spécifier plusieurs classes pour un même élément. C’est très simple : on utilise toujours l’attribut class mais on sépare les noms des classes par une espace. Par exemple, on peut faire class="rempli-en-rouge bords-en-bleu".

Précision sur la zone de dessin svg

Nous avons déjà vu que la racine d’un document SVG doit être l’élément svg. Il est néanmoins possible d’intégrer d’autres balises svg à l’intérieur du dessin. On peut donc écrire :

<]]> < Plusieurs balise SVG dans un dessin ]]>
Utilisation d’une feuille de style externe pour styler un carré

Pour rappel, les commentaires en CSS sont délimités par /* et */. Ils peuvent être placés n’importe où.

Rien de bien compliqué : le troisième svg est situé par rapport aux second svg. Ses coordonnées dans le premier svg sont donc 50+30,40+80 soit 80,120 (on ajoute les coordonnées des second et troisème svg).

Intéressons nous maintenant à la zone de dessin en elle même : si je vous demande comment on dessine le premier pixel (celui tout en haut à gauche), vous me répondez ? Ceux qui sont habitués à travailler sur du bitmap pensent sans doute qu’il faut écrire :

< Comment dessiner un pixel en SVG ? ]]>

Et bien non ! En fait, les points de coordonées 1,1, 10,20, 400,300, etc ne désignent pas des pixels mais les intersections des lignes des abscisses et des ordonnées. Pour dessiner le pixel tout-en-haut-à-gauche, on devra faire :

< Comment dessiner un pixel en SVG ? Avec un carré de côté 1 ! ]]>

Voici un schéma pour bien visualiser la chose.

Les briques graphiques

Dans un dessin vectoriel, on a souvent besoin de réutiliser des formes déjà créées. À notre niveau, si on souhaite dessiner trois sapin, on devra à chaque fois redessiner toutes les formes en prenant soin de recalculer leurs coordonnées. SVG permet heureusement de regrouper plusieurs formes dans une seule balise dans le but de pouvoir réutiliser cette « brique graphique ». On utilisera la balise g.

Essayons d’abord de dessiner un sapin dans une balise g :

<]]> < Exemple d’utilisation de la balise g ]]>
Exemple d’utilisation de la balise g

Je suis nul en dessin

Comme vous le voyez, la balise g ne change strictement rien : sans elle, il serait dessiné exactement la même chose. C’est maintenant que ça va devenir intéressant : il est possible de réutiliser ce dessin grâce à l’ élément use. use doit avoir un attribut xlink:href (qui appartient à l’espace de nommage XLink) qui pointe vers une balise g. On aura pris soin d’attribuer un id à notre brique graphique. L’élément use accepte aussi les attributs x et y mais nous allons plutôt nous servir de quelquechose que nous avons vu pour replacer notre brique : les transformations. Pour une meilleur lisibilité, on n’utlisera que l’attribut transform (et non pas x et y). Exemple avec des translations :

<]]> < Exemple de réutilisation d’une brique graphique ]]>
Exemple de réutilisation d’une brique graphique

Tout simplement :). Et ça marche aussi avec scale :

<]]> < Exemple de réutilisation d’une brique graphique ]]>

Le changement d’échelle a bien sur pour point d’origine le coin haut gauche de notre brique graphique. Essayons avec rotate, skewX et skewY :

<]]> < Exemple de réutilisation d’une brique graphique ]]>
Exemple de réutilisation d’une brique graphique

Vous avez remarqué que la rotation ne s’est pas faite à partir du coin haut droit de la zone de dessin svg mais du point de coordonnées 0,0 de notre brique graphique g. C’est pourquoi il peut paraître utile de centrer notre dessin contenu dans notre g. C’est en fait très facile : il suffit d’utiliser des coordonnées négatives. Exemple :

<]]> < L’art de centrer le contenu de ses briques graphiques g ]]>
L’art de centrer le contenu de ses briques graphiques g

Maintenant, on aimerais éviter le dessin en haut à gauche. En fait, on souhaite déclarer notre dessin sans l’afficher puis l’utiliser ensuite. SVG met a disposition la balise defs qui contient tout ce qu’on défini et qu’on souhaite utiliser ensuite. Les balises contenus dans defs ne seront donc jamais affichées directement. Dans notre cas, nous pouvons faire :

<]]> < La balise defs ]]>
La balise defs

C’est aussi dans cette balise que nous stockerons les dégradés, les motifs, etc.

use étant une balise XML, on peut la styler comme les autres. Mais que va-t-on styler au juste puisque la balise use ne s’affiche pas à proprement parler ? Et bien c’est ce qui est appelé qui sera stylé, ou restylé pusqu’il aura déjà les styles appliqués sur lui avant :

<]]> < La balise use et CSS ]]>
La balise use et CSS

En CSS, le sélecteur « + » est appelé « sélecteur d’enfants adjacent ».
Dans l’expression balise1 + balise2, la balise concernée est balise2. On pourrait traduire par toutes les balise2 précédées par un balise1.
Spécification

Je crois que cet exemple montre bien la simplicité de la programmation en SVG et la puissance de ce langage. Et vous n’avez encore rien vu >:).

Pour favoriser l’accessibilité, il peut être utile d’indiquer un titre et une description sur chaque élément de notre dessin. L’élément g accepte justement les attributs title et desc. Ne nous en privons pas : ça nous facilitera la relecture.

Les liens menant hors du contenu SVG

Il existe deux types de liens : les liens menant hors du contenu SVG et les liens menant dans un contenu SVG. À notre stade, nous ne nous intéresserons pas au deuxième type de lien faisant appel à des connaissance que nous n’avons pas (encore).

SVG utilise XLink pour les liens. Comme en XHTML, l’élément qui permet de décrire un lien est a. Deux attributs nous seront utiles : xlink:href et xlink:title. Seuls les liens de type simple sont autorisés en SVG. On mettra les objets qu’on voudra lier dans la balise a. Exemple :

<]]> < Les liens en SVG ]]>
Les liens en SVG

Il est impératif d’écrire l’attribut xlink:title même si certaines implémentations ne le rendent pas (notamment le viewer SVG d’Adobe, version 6 bêta). En effet, en XHTML, on a la plupart du temps du texte dans la balise a ce qui n’est pas toujours le cas en SVG. Ici, sans xlink:title, on ne sait pas où on va.

Les images

Il est possible d’afficher des images PNG, JPEG et SVG grâce à la balise image. Cet affichage se fait très simplement grâce aux attributs x et y, optionnels et par défaut à 0, width et height qui eux sont requis. Par défaut, le ratio de l’image est conservé, ce qui veut dire que si les attributs width et height renseigné dans le document SVG ne sont pas les mêmes que les longueur et largeur de l’image, elle ne sera pas étirée mais elle conservera son ratio et sera centrée à l’intérieur du rectangle de coordonnées (x,y), de longueur width et de hauteur height. Le lien vers l’image est réalisé via l’attribut xlink:href. Prenons par exemple cette image :

Photo d’un palmier

<]]> < Insérer une image bitmap en SVG ]]>
Insérer une image bitmap en SVG

Ici, pas de problème : les longueurs sont respectées. Mais il peut en être autrement :

<]]> < Insérer une image bitmap en SVG, avec des rapports longueur/largeur différents ]]>
Insérer une image bitmap en SVG, avec des rapports longueur/largeur différents

Le viewer d’Adobe semble ne pas supporter cette partie de la spécification.

On peut contrôler la manière dont la ratio est conservé ou décider qu’il ne doit pas être conservé, mais cela fait appel à des notions plutôt compliquées que nous verrons plus tard.

Les attributs communs

En attendant que xml:id soit reconnu par les parsers XML, il est possible d’attribuer à tous les éléments SVG l’attribut id. Il devient ainsi facile de manipuler un document XML via l’API DOM, avec le langage de script ECMAScript par exemple.

De même, l’attribut xml:base peut être appliqué à toutes les balises SVG. Cet attribut sert à désigner un chemin de base du tous les chemins relatifs enfants. En gros, lorsque vous vous affichez xlink:href="image.jpg", le navigateur va chercher l’image dans le répertoire dans lequel se situe le dessin SVG. Avec l’attribute xml:base, on ira chercher l’image spécifiée dans le répertoire indiqué par l’attribut.

<]]> < Utilisation de xml:base ]]>

Il deux autres attributs de l’espace de nommage xml : xml:lang et xml:space.

Pour le référencement, il est préférable d’indiquer la langue du document grâce à xml:lang, même si ce n’est pas obligatoire. Ensuite, on peut placer cet attribut sur les éléments susceptibles de contenir du texte. svg est bien susceptible de contenir du texte tandis que des balises comme rect ou ellipse n’en contiendrons jamais.

xml:space, tout comme xml:lang ne s’applique qu’aux éléments pouvant contenir du texte. Il accepte de valeurs : default (valeur par défaut) et preserve.

Nous reviendront sur ces deux attributs lors du chapitre traitant du texte.

Maintenant que nous savons bien organiser un document SVG, nous allons voir quelquechose de beaucoup plus compliqué : les paths O:).

Les transformations
Les chemins