10 - Introduction à SVG


Lien vers le tutoriel original : http://alignedleft.com/tutorials/d3/an-svg-primer ² ———-

Introduction à SVG

Dernière mise à jour le 20 mai 2014

D3 se montre vraiment utile lorsqu’il s’agit de manipuler des graphiques vectoriels SVG. Dessiner avec des divs et d’autres éléments natifs HTML est possible, mais un peu maladroit et sujet aux incohérences habituelles entre différents navigateurs. Utiliser SVG est plus fiable, visuellement cohérent, et plus rapide.

Des logiciels de dessin vectoriels comme Illustrator peuvent être utilisés pour générer des fichiers SVG, mais nous devons apprendre à les générer avec du code.

L’élément SVG

Scalable Vector Graphics (SVG, ou graphique vectoriel adaptable, selon Wikipédia) est un format d’image basé sur du texte. Chaque image SVG est définie en utilisant un langage balisé similaire à HTML. Le code SVG peut être inclus directement dans un document HTML. Chaque navigateur supporte SVG à l’exception d’ Internet Explorer versions 8 et plus anciennes. SVG est basé sur XML, donc vous verrez que les éléments qui n’ont pas de balises fermantes doivent être auto-fermant. Par exemple :

<element></element>   <!-- Utilise une balise fermante -->
<element/>            <!-- Balise auto-fermante -->

Avant de pouvoir dessiner quoi que ce soit, vous devez créer un élément SVG. Pensez à l’élément SVG comme à un canevas (ou une toile, en anglais : canvas) sur lequel nos visuels vont être dessinés. (À cet égard, SVG est conceptuellement similaire à l’élément HTML canvas.) Au minimum, il est bon de spécifier les valeurs de largeur width et de longueur height. Si vous ne les spécifiez pas, SVG prendra autant de place qu’il pourra dans l’élément qui le contient.

<svg width="500" height="50">
</svg>

Voilà le SVG généré par ce code :

Vous le voyez pas ? Cliquez-droit sur l’espace vide au-dessus et choisissez “Right-click on the empty space above and choose “Inspecter l’élément”. Votre inspecteur web devrait ressembler à ça :

Inspection d'un SVG vide

Notez qu’il y a un élément svg (ouais !), et qu’il occupe 500 pixels en horizontal et 50 pixels en vertical. C’est juste qu’il a pas l’air de grand chose, pour l’instant (ouh !).

Notez également que le navigateur assume que l’unité de mesure par défaut est le pixel. On a spécifié des dimensions de 500 et 50, pas 500px et 50px. On aurait pu spécifier px de manière explicite, ou n’importe quel nombre dans les unités supportées, qui comprennent notamment em, pt, in, cm, et mm.

Formes simples

Il existe un certain nombre d’éléments visuels que vous pouvez inclure entre ces balises svg, par exemple rect, circle, ellipse, line, text, et path.

Si vous êtes familiés avec la programmation de visuels sur ordinateur, vous reconnaîtrez le système usuel de coordonnées basé sur le pixel, dans lequel 0,0 correspond au coin en haut à gauche du canevas. En augmentant la valeur x on va vers la droite, tandis qu’en augmentant la valeur y on va vers le bas.

0,0 100,20 200,40

rect dessine un rectangle. Utilisez x et y pour spécifier les coordonnées du coin haut-gauche, et width et height pour spécifier ses dimensions (respectivement largeur et hauteur). Ce rectangle remplit l’espace de notre SVG :

<rect x="0" y="0" width="500" height="50"/>

circle dessine un cercle. Utilisez cx et cy pour spécifier les coordonnées de son centre, et r pour spécifier son rayon. Ce cercle est centré au milieu de notre SVG large de 500 pixels, car sa coordonée cx (“centre-x”) est 250.

<circle cx="250" cy="25" r="25"/>

ellipse est similaire, mais requiert deux valeurs de rayon pour chaque axe. À la place de r, utilisez rx et ry.

<ellipse cx="250" cy="25" rx="100" ry="25"/>

line dessine une ligne. Utilisez x1 et y1 pour spécifier les coordonnées d’un bout de la ligne, et x2 et y2 pour l’autre bout. Une couleur de trait stroke doit être spécifiée pour que la ligne soit visible.

<line x1="0" y1="0" x2="500" y2="50" stroke="black"/>

text dessine un texte. Utilisez x pour spécifier la position du bord gauche, et y pour spécifier la position verticale de la ligne de base (baseline).

<text x="250" y="25">Trop facile</text>
Trop facile

text héritera des styles CSS de fonte de son élément parent à moins que l’on ne spécifie autre chose. (On s’étendra plus sur la manière de formater le texte dans un instant.) Notez comment le style du texte ci-dessus correspond à celui de ce paragraphe. On pourrait écraser ce format comme cela :

<text x="250" y="25" font-family="sans-serif"
 font-size="25" fill="gray">Trop facile</text>
Trop facile

Notez également que lorsqu’un élément visuel s’étale au-dela d’un bord du SVG, il est coupé. Faites attention, lorsque vous utilisez text, que vos descendeurs (les parties d’un caractère qui dépassent) ne soient pas coupés (ouille !). Vous pouvez voir ce que ça se produit lorsqu’on place la ligne de base (y) à 50, la même que la hauteur de notre SVG :

<text x="250" y="50" font-family="sans-serif"
 font-size="25" fill="gray">Trop facile</text>
Trop facile

path permet de dessiner des formes plus complexes que celles au-dessus (comme les frontières d’un pays dans les cartes (geomaps)), et sera expliqué séparément. Pour l’instant, on travaillera avec des formes simples.

Styliser les éléments SVG

Le style par défaut de SVG est un remplissage noir sans contour. Si vous voulez quoi que ce soit d’autre, vous devrez appliquer un style à vos éléments. Les propriétés SVG les plus courantes sont :

  • fill — Le remplissage, une valeur de couleur. Comme avec CSS, les couleurs peuvent être spécifiées comme suit

    • couleurs nommées — orange
    • valeurs hexadécimales — #3388aa ou #38a
    • valeurs RGB — rgb(10, 150, 20)
    • valeurs RGB avec transparence alpha — rgba(10, 150, 20, 0.5)
  • stroke — Le trait (ou contour), une valeur de couleur.
  • stroke-width — La largeur du trait, une valeur numérique de mesure (typiquement en pixels).
  • opacity — L’opacité, une valeur numérique comprise entre 0.0 (complètement transparent) et 1.0 (complètement opaque).

Avec text, vous pouvez aussi utiliser ces propriétés, qui fonctionnent comme avec CSS :

  • font-family
  • font-size

Comme avec CSS, il y a deux moyens d’appliquer un style à un élément SVG : soit directement en ligne (inline) comme un attribut de l’élément, soit avec une règle CSS.

Voilà quelques propriétés de style appliquées directement sur un cercle circle comme attributs :

<circle cx="25" cy="25" r="22"
 fill="yellow" stroke="orange" stroke-width="5"/>

Alternativement, on pourrait enlever tous les attributs de style, et assigner une classe à circle (comme si c’était un élément HTML normal)

<circle cx="25" cy="25" r="22" class="pumpkin"/>

et mettre les règles fill, stroke, et stroke-width dans un style CSS qui ciblerait une nouvelle classe :

.pumpkin {
    fill: yellow;
    stroke: orange;
    stroke-width: 5;
 }

L’approche CSS à des avantages évidents :

  1. Vous pouvez spécifier un style une fois et l’appliquer à plusieurs éléments.
  2. Le code CSS est généralement plus facile à lire que les attributs en ligne.
  3. Pour ces raisons, l’approche CSS est plus maintenable et permet d’implémenter plus rapidement des changements de style. Utiliser CSS pour appliquer des styles SVG peut en déconcerter certains. fill, stroke, et stroke-width, ne sont, après tout, pas des propriétés CSS. (Les équivalents CSS les plus proches sont background-color et border.) Si ça peut vous aider à vous rappeler quelles règles sont spécifiques à SVG dans votre feuille de style, vous pouvez inclure svg dans ces sélecteurs :
svg .pumpkin {
    /* ... */
 }

Calques (layers) et ordre de dessin

Il n’y a pas de “calques” en SVG, et pas de vrai concept de profondeur. SVG ne supporte pas la propriété CSS z-index, donc les formes sont organisées automatiquement dans un plan bi-dimensionnel x/y.

Et pourtant, si on dessine plusieurs formes, elles se superposent :

<rect x="0" y="0" width="30" height="30" fill="purple"/>
<rect x="20" y="5" width="30" height="30" fill="blue"/>
<rect x="40" y="10" width="30" height="30" fill="green"/>
<rect x="60" y="15" width="30" height="30" fill="yellow"/>
<rect x="80" y="20" width="30" height="30" fill="red"/>

L’ordre dans lequel les éléments sont codés détermine leur profondeur. Le carré violet apparait en premier dans le code, donc il est dessiné en premier. Ensuite, le carré bleu est dessiné “par dessus” le violet, puis le carré vert et ainsi de suite.

Pensez aux formes SVG comme à des formes peintes sur une toile. La peinture-pixel qui est appliquée plus tard masque ce qui aurait été peint avant, et par là apparait comme étant “devant.”

Cet aspect d’ordre de dessin est important lorsque vous avez des éléments visuels qui ne devraient pas être cachés par d’autres. Par exemple, vous pourriez avoir des axes ou des étiquettes qui apparaissent sur un nuage de point (scatterplot). Les axes ainsi que les étiquettes devraient être ajoutés au SVG en dernier, pour qu’ils apparaissent devant tous les autres éléments.

Transparence

La transparence peut être utile lorsque des éléments de votre visualisation se superposent mais qu’ils doivent rester visibles, ou lorsque vous voulez désaccentuer (de-emphasize) certains éléments pour en mettre d’autres en valeur.

Il y a deux moyens d’appliquer une transparence : utilisez une couleur RGB avec alpha, ou définir une valeur d’opacité opacity.

Vous pouvez utiliser rgba() n’importe où pour spécifier une couleur, comme avec fill ou stroke. rgba() attend trois valeurs entre 0 et 255 pour le rouge, le vert et le bleu, plus une valeur alpha (transparence) entre 0.0 et 1.0.

<circle cx="25" cy="25" r="20" fill="rgba(128, 0, 128, 1.0)"/>
<circle cx="50" cy="25" r="20" fill="rgba(0, 0, 255, 0.75)"/>
<circle cx="75" cy="25" r="20" fill="rgba(0, 255, 0, 0.5)"/>
<circle cx="100" cy="25" r="20" fill="rgba(255, 255, 0, 0.25)"/>
<circle cx="125" cy="25" r="20" fill="rgba(255, 0, 0, 0.1)"/>

Notez qu’avec rgba(), la transparence est appliquée à fill et stroke indépendamment. Les cercles qui suivent ont une valeur de remplissage fill opaque à 75%, tandis que leur couleur de contour strokes est opaque à seulement 25%.

<circle cx="25" cy="25" r="20"
        fill="rgba(128, 0, 128, 0.75)" 
        stroke="rgba(0, 255, 0, 0.25)" stroke-width="10"/>
<circle cx="75" cy="25" r="20"
        fill="rgba(0, 255, 0, 0.75)"
        stroke="rgba(0, 0, 255, 0.25)" stroke-width="10"/>
<circle cx="125" cy="25" r="20"
        fill="rgba(255, 255, 0, 0.75)"
        stroke="rgba(255, 0, 0, 0.25)" stroke-width="10"/>

Pour appliquer une transparence à tout un élément, définissez un attribut opacity. Voilà quelques cercles complètement opaques

suivis par les mêmes cercles, avec des valeurs d’opacité :

<circle cx="25" cy="25" r="20" fill="purple" 
        stroke="green" stroke-width="10"
        opacity="0.9"/>
<circle cx="65" cy="25" r="20" fill="green"
        stroke="blue" stroke-width="10"
        opacity="0.5"/>
<circle cx="105" cy="25" r="20" fill="yellow"
        stroke="red" stroke-width="10"
        opacity="0.1"/>

Vous pouvez utiliser opacity sur un élément qui a déjà des couleurs définies avec rgba(). Lorsque vous faites cela, les transparences se multiplient. Les cercles qui suivent utilisent les mêmes valeurs RGBA pour fill et stroke. Le premier cercle ci-dessous n’a pas d’attribut opacity de défini, mais les deux autres l’ont :

<circle cx="25" cy="25" r="20"
        fill="rgba(128, 0, 128, 0.75)" 
        stroke="rgba(0, 255, 0, 0.25)" stroke-width="10"/>
<circle cx="65" cy="25" r="20"
        fill="rgba(128, 0, 128, 0.75)" 
        stroke="rgba(0, 255, 0, 0.25)" stroke-width="10"
        opacity="0.5"/>
<circle cx="105" cy="25" r="20"
        fill="rgba(128, 0, 128, 0.75)" 
        stroke="rgba(0, 255, 0, 0.25)" stroke-width="10"
        opacity="0.2"/>

Notez que l’opacité opacity du troisième cercle est égale à 0.2 soit 20%. Et pourtant son remplissage violet a déjà une valeur alpha de 0.75 ou 75%. La zone violette a donc une transparence finale de 0.2 fois 0.75 = 0.15 ou 15%.

Pour plus d’informations sur SVG — notamment les chemins paths, clip-paths, masks, et filters — voir “An SVG Primer for Today’s Browsers” de David Dailey.