SVGround : cours SVG

Les chemins (path)

Vous souvenez vous des transformations ? Je vous avais dit qu’il existait une autre transformation, générique, que translate, rotate, scale, skewX et skewY : matrix. Étant donné que nous pouvions déjà tout faire et que je ne comprends pas un pet de calcul matriciel, nous l’avions passé. Maintenant, repensons aux formes. L’intitulé du chapitre était Les formes de base. Et c’est vrai que ce n’était que des formes de base : on ne pouvait pas, jusqu’ici, dessiner de courbes, d’arcs, bref : des formes compliquées. C’est là qu’intervient path : c’est une balise générique qui permet de tracer toutes les formes possibles et imaginables ! Pourquoi alors avoir étudier des formes qu’on va de toute façon pouvoir créer avec path ? Et bien pour deux raisons. La première est qu’un rect désigne un rectangle tandis qu’un path désigne une forme : sémantiquement parlant, on utilise rect pour dessiner un rectangle et path pour dessiner une forme (qui peut être un rectangle mais on n’en sait rien). La seconde, c’est qu’utiliser des balises appropriées permet une relecture beaucoup plus facile.

La balise path

Ça en étonnera peut être certains, mais il suffit d’une balise pour dessiner un path : c’est path. Cette balise accepte bien sur tous les attributs qui nous permettent de styler nos formes, c’est à dire style, class et id. Elle n’a qu’un attribut obligatoire : d pour datas (données).

Les paths, ou plus particulièrement les données contenues dans l’attribut d sont organisées par commandes. Il y a dix commandes, chacune représentée par une lettre (M, Z, L, H, V, C, S, Q, T ou A). Chacune de ces commandes donne le tracé d’une ligne grâce à un ou plusieurs couples de coordonnées (ça dépend de la commande).

Les commandes Moveto et Lineto

Première commande : la commande Moveto, notée M, qui prend en paramêtre les coordonnées du premier point du chemin. Elle peut être décrite par cette phrase : « Je déplace le crayon jusqu’au point des coordonnées indiquées et je le pose. ». La seconde commande est la commande Lineto, notée L, qui trace une ligne des dernières coordonnées aux coordonnées indiqués. Avec ces deux commandes, on peut faire tout ce qu’on faisait avec polyline :

<]]> < Les commandes Moveto et Lineto des paths SVG ]]>
Les commandes Moveto et Lineto des paths SVG

Rien de bien compliqué : ça marche comme polyline, avec les L en plus. Vous remarquerez que notre figure a été remplie d’une manière un peu étrange. En fait, pour la remplir, le processeur SVG a tracé une ligne de la dernière paire de coordonnées à la toute première. Si on ne veut pas de remplissage, on doit mettre fill:none;.

La commande Closepath

Si les commandes Moveto et Lineto suffisent à émuler un polyline, il faut une troisième commande pour avoir le même résultat qu’un polygon qui, rappelons le, a pour seule différence de « fermer » le chemin en traçant une ligne du dernier couple de points au premier. Cette commande s’appelle Closepath et la lettre qui la désigne est Z.

<]]> < La commande Closepath ]]>
La commande Closepath

Simplissime ! Utilisez cette commande à chaque que vous voulez clore un path. Je m’explique : certains d’entre vous se sont sans doute dit que cette commande ne servait pas à grand chose puisqu’on pouvait aisément tracer la ligne fermante, en quelque sorte fermer le chemin « manuellement ». C’est une erreur : dans le cas ou on ferme le chemin manuellement, les deux segments vont se superposer, mais il y aura deux extrémités ; dans le cas ou c’est fait proprement, avec la commande appropriée (cest à dire la commande Closepath), la forme n’a pas d’extrémité. sans importance ? N’oubliez pas que deux propriétés CSS existent pour contrôler le rendu des extrémités et des jointures : stroke-linecap et stroke-linejoin. Exemple :

<]]> < Problème lors de la fermeture manuelle d’un path ]]>
Problème lors de la fermeture manuelle d’un path

Les Lineto horizontaux et verticaux

Il y a deux raccourcis pour tracer des lignes horizontales ou verticales : les Lineto horizontaux (commande H) et les Lineto verticaux (commande V). Préférez toujours ces commandes à la commande Lineto (lettre L) qui est moins lisible et moins rapide. Les commandes H et V doivent être suivis d’un seul nombre : la coordonnée en abscisse (pour la commande H) ou en ordonnée (pour la commande V) du point d’arrivée. On peut ainsi facilement tracer un carré comme ceci :

<]]> < Tracer des lignes horizontales et verticales avec les commandes H et V ]]>
Tracer des lignes horizontales et verticales avec les commandes H et V

Plusieurs sous-tracés

Les possibilités de SVG ne s’arrêtent pas là. Il est possible, grâce à la commande M, de dessiner plusieurs sous-tracés dans un seul path. Même si ça ne paraît pas forcément utile, vous verez qu’on pourra s’en servir pour mettre du texte sur un path ou faire de l’animation. En ce qui concerne les possibilités de la commande Moveto, je vous avais dit que M x,y correspondait à la phrase Je déplace le crayon jusqu’au point de coordonnées x,y et je le pose. La formulation peut paraître puérile mais la commande Moveto fonctionne exactement comme ça (en supposant qu’à l’apparition d’un M, le crayon est levé). Voici un exemple d’utilisation :

<]]> < Plusieurs sous-tracés avec la commande M ]]>
path{ stroke:palevioletred; stroke-linejoin:round; stroke-width:6px; fill:none; }
Plusieurs sous-tracés avec la commande M

On peut bien sur faire une infinité de sous-tracés. L’avantage est qu’on peut dessiner plusieurs formes avec un seul tracé et qu’on pourra changer le style de toutes ces formes en même temps, en attribuant le style adéquat au path.

Des coordonnées relatives

Il est possible, et ça va nous simplifier la vie, de préciser que les coordonnées qu’on indique dans un path sont relatives. Il suffit pour cela de mettre les lettres qui indiquent les comamndes en… minuscule ! On peut bien sur varier, et spécifier que certaines coordonnées sont relatives tandis que d’autres sont absolues.

<]]> < Des coordonnées relatives pour l’élément path ]]>
Des coordonnées relatives pour l’élément path

Les coordonnées relatives sont quand il s’agit de répéter un motif. Dans notre cas, après avoir écrit h 20 v 20 , il suffit de faire des copier/coller pour finir le dessin, d’où un important gain de temps. Avec des coordonnées absolues, on aurait du écrire quelquechose commençant par d="M 10,10 H 30 V 30 H 50 V 50…". Fastidieux.

On peut se demander ce qui se passerait si on mettais un m minuscule pour la commande Moveto. En fait, c’est assez simple : si ce m minscule est la première commande du tracé, SVG considère que les coordonnées sont absolues. Sinon, elle considère que les coorodnnées sont relatives et agit en conséquence en ajoutant les coordonnées aux dernières coordonnées indiqués. Par exemple :

<]]> < Des coordonnées relatives pour la commande Moveto ]]>
Des coordonnées relatives pour la commande Moveto

Le tracé commence au point de coordonnées 100,100, même si m est en minuscule (parceque de toute façon, quand c’est la première commande, ça ne peut être relatif à rien) puis va jusqu’au point de coordonnée 230,140 (L 230,140). Ensuite, le second sous-tracé commence au point de coordonnées xdernier point+xm,ydernier point+ym soit 230+(-200),140+100 soit 30,240. Puis une ligne horizontale de 300 pixels est tracée.

Pour la commande Closepath (lettre Z), la casse (entendez : le fait que la lettre soit majuscule ou minuscule) ne change rien : la commande va fermer le sous-tracé courrant en rejoignant le dernier point au premier.

Les arcs elliptiques

Comme vous venez de vous en rendre compte, c’est maintenant que ça se corse >:D ! Pour commencer par le début, qu’est ce qu’un arc elliptique ? Vous vous souvenez d’avoir tracé des ellipses ? Et bien un arc elliptique est un morceau, une portion d’ellipse.

Tracer un arc elliptique requiert beaucoup d’informations. Alors qu’il n’en fallait que deux (au maximum) pour tracer un ligne droite, il en faut maintenant sept ! Il faut déjà deux points, soit quatres nombres, pour tracer les deux ellipses dont l’axe des x est parallèle à l’axe des ordonnées. Mais comme ce n’est pas toujours le cas, il faut aussi connaître l’inclinaison de cet axe !

Commençons par le début : la lettre qui commande le tracé d’un arc elliptique est A (ou a minuscule pour des coordonnées relatives). Les deux premiers paramêtres sont respectivement la longueur du rayon x et la longueur du rayon y (ces deux rayons restent perpendiculaires).
Le troisième est la rotation (sens direct, inverse des aiguilles d’une montre) en degrés de l’axe x de l’ellipse par rapport à l’axe des ordonnées.
Le quatrième paramêtre, appelé large-arc-flag, indique si on doit afficher l’arc dont la mesure fait plus de la moitié du périmètre de l’ellipse (dans ce cas, la valeur est 1), ou l’arc dont la mesure fait moins de la moitié du périmètre (valeur : 0).
Le cinquième paramêtre, appelé sweep-flag, indique quant à lui si l’arc doit être dessiné dans la direction négative des angles (dans lequel cas sa valeur est 0) ou dans la direction positive des angles (valeur : 1). Les deux derniers sont les coordonnées du point d’arrivée, les coordonnées du point de départ étant données par la commande précédent la commande A.

La commande d’arc elliptique est à mon sens assez difficile à comprendre, mais une fois assimilée, elle est très simple d’utilisation. Il faut souvent beaucoup de tests avant de comprendre comment elle fonctionne. Voici un exemple très simple :

<]]> < Des arcs elliptiques simples ]]>
Des arcs elliptiques simples

À vous de tester toutes les possibilités, elles sont énormes. On peut d’ailleurs facilement créer un cercle avec cette commande :

<]]> < Un cercle grâce à la commande d’arc elliptique ]]>
Un cercle grâce à la commande d’arc elliptique

Pour comprendre :

Un cercle grâce à la commande d’arc elliptique : schéma

Rien de bien compliqué en fait ^^' si ? Le problème de ces courbes est qu’elles ne permettent pas encore de faire tout ce que l’on voudrais. Passons aux choses sérieuses avec les courbes de Bézier…

Les courbes de Bézier quadratiques

La commande Q

Les courbes de Bézier (du nom d’un ingénieur de Renault) quadratiques n’ont besoin que de trois paramêtres : le point de départ, le point d’arrivée et un point de contrôle. En SVG, le point de départ est donné par la commande précédente. Si vous avez déjà fait du dessin vectoriel avec un logiciel de graphisme (Paint par exemple), vous avez sans doute déjà tracé une courbe de Bézier. On commence d’abord par tracer un segment puis on place ce fameux point de contrôle, aussi appelé point d’inflexion. Pour comprendre le fonctionnement d’une telle courbe, il faut imaginer que notre segment est un fil de métal qui est attiré par l’aimant qu’est le point de contrôle. Plus une partie du fil se trouve près de l’aimant, plus elle est attirée et se déforme.

Prenons un premier exemple. La lettre qui désigne cette commande est Q. Elle peut évidemment être écrite en minuscule, ce qui signifiera que les coordonnées indiquées sont relatives. Cette commande requiert deux paramêtres et au final qutre nombres : les coordonnées du point d’inflexion et les coordonnées du point d’arrivée.

<]]> < La commande de courbe de Bézier quadratique ]]>
La commande de courbe de Bézier quadratique

Dans le second path, on a mis la lettre q en minuscule. Cette fois ci, ce sont les deux paires de coordonnées qui sont relatives !
d="M 50,200 q 340,40 300,0" est équivalent à
d="M 50,200 Q 390,240 350,200".
Ultra-simple, non ? Et bien si ce n’est pas clair, voici un schéma qui devrait aider à comprendre le mécanisme des courbes de Bézier : on a connecté les points de départ et d’arrivée au point de contrôle. Puis, on a relié les milieux des deux segments obtenus :

N’hésitez pas à regarder la source de ce schéma : c’est en lisant du code que l’on apprend. Normalement, vous ne devriez butter que sur deux attributs :p. Vous pouvez accéder à tous les exemples et schémas du cours à cette adresse.

Vous l’avez remarqué : le milieu du segment (en jaune sur le schéma) qui relie les milieux des deux segments reliants les points de départ et d’arrivée au point d’inflexion « touche » la courbe quadratique (8o c’est plus clair sur le dessin, non ?). Une fois que c’est compris, vous ne devriez plus avoir de problème avec ces courbes.

La commande T

On pourrait définir la commande T comme complémentaire à la commande Q. En clair, elle ne permet pas de tracer une nouvelle courbe, elle se contente de finir une courbe de Bézier quadratique (Q) de la manière la plus naturelle possible. Elle doit donc toujours venir après une commande Q (ou q minuscule) ou une commande T. Elle peut, comme d’habitude, être relative (dans ce cas on écrit la lettre en minuscule). Exemple :

<]]> < La commande T ]]>
La commande T

On devine facilement que le point d’inflexion de la seconde partie de la courbe est en fait le symétrique du premier point d’inflexion par rapport au point d’arrivé de la première partie de la courbe, qui est aussi le point de départ de la seconde.

Les courbes de Bézier cubiques

Les courbes de Bézier cubiques sont semblables aux courbe de Bézier quadratiques à la différence qu’il n’y a plus un seul point de contrôle, mais deux. Les possibilitées en sont d’autant plus élevées !

La commande C

La commande C prend trois paramêtres : les coordonnées du premier point d’inflexion, les coordonnées du second et les coordonnées du point d’arrivée. J’espère qu’il n’est plus la peine de préciser qu’elle peut être écrite en minuscule pour des coordonnées relatives .

<]]> < La commande C ]]>
La commande de courbe de Bézier cubique

En fait, il se passe la même chose que tout à l’heure. Relions d’abord le point de départ au point d’inflexion №1, puis le point d’inflexion №1 au point d’inflexion №2, etc. Puis, relions les milieux de ces 3 segments pour en obtenir deux, puis les milieux de ces deux-ci pour en obtenir 1 :

Ce point touche le path ! Dans ce cas, ce n’est pas très facile à visualiser, mais dans certains autres, si ! Je vous le jure :D !

La commande S

Vous vous en doutiez surement : il existe une commande pour terminer de façon naturelle une courbe de Bézier cubique. C’est la commande S, qui prend non pas une mais deux paires de coordonnées : la première paire est les coordonnées du second point de contrôle et la seconde les coordonnées du point d’arrivé. Le premier point d’inflexion est calculé à partir de la commande précédente, qui est obligatoirement une commande de courbe de Bézier cubique, donc une commande C ou une commande S.

<]]> < La commande S ]]>
La commande S

Voilà, on a fait le tour des courbes dessinables avec SVG. Vous pouvez bien sur juxtaposer plusieurs courbes de Bézier : on peut avoir des résultats étonnants. À vous de tester ces différentes commandes. Ça viendra d’autant plus facilement que vous écrirez du code. C’est comme tous les autres langages, informatiques ou pas.

Simplification de la notation des path

La longueur des données contenus dans l’attribut d des path peut être très importante, d’où le besoin de simplification.

Vous n’êtes pas obligés de simplifier la notation de vos path, cela peut vite devenir illisible !

Notation générale

Il n’est pas nécessaire d’inclure une espace entre un nombre et une lettre. De même, il n’est pas nécessaire d’inclure une espace entre un nombre positif et un nombre négatif, le signe moins (-) permettant de faire la différence.

Ceci :
d="M 40,40 L 25,90 L 97,-85 H 20"
peut donc être écrit :
d="M40,40L25,90L97-85H20"
(qui est nettement moins lisible).

Deux nombres peuvent être séparés par une virgule ou une espace. Dans ces cours, seuls les coordonnées sont séparées par des virgules, mais rien ne vous empêche de faire autrement !

Commandes Lineto raccourcies

Il faut toujours préférer les commandes H et V pour tracer des lignes horizontales ou verticales. Elles sont plus rapides et plus lisibles.

Suites de commandes identiques

Lorsque plusieurs commandes identiques se suivent, il est possible de ne spécifier qu’une seule fois (la première fois) la lettre indiquant la commande. Par exemple, dans l’exemple précédent :
d="M 40,40 L 25,90 L 97,-85 H 20"
peut être noté
d="M 40,40 L 25,90 97,-85 H 20".
Ceci est valables pour les commandes L (Lineto), H (Lineto horizontal), V (Lineto vertical), C (courbe de Bézier Cubique), S, Q (courbe de Bézier quadratique), T et A (arc elliptique).

Commande Moveto avec plusieurs paires de coordonnées

Si une commande Moveto a plusieurs paires de coordonnées, les paires suivant la première sont considérées comme des commandes Lineto. Par exemple :
d="M 100,100 L 300,500 L 20,10"
équivaut à :
d="M 100,100 300,500 20,10".
Si m est écrit en minuscule, les Lineto suivants ne seront pas absolus, mais relatifs :
d="M 100,100 l -50,10 l 20,20"
s’écrira :
d="m 100,100 -50,10 20,20".

Les marqueurs

Comme vous le savez maintenant, les path ont de multiples sommets, qui correspondent aux points de départ et d’arrivé des différentes commandes disponibles. SVG permet d’assigner à ces sommets des objets graphiques de toutes sortes : les marqueurs. Les marqueurs sont très utiles pour créer des flèches.

On utilise pour cela la balise marker qui n’est jamais dessinée directement, mais qu’on place tout de même dans l’élément defs, comme tous les objets graphiques réutilisables. Pour assigner un marker à un path, on utilise la propriété CSS marker qui prend comme valeur l’URI du marqueur (ou « none » qui est la valeur par défaut). C’est pourquoi nos marqueurs auront toujours un attribut id qui permettra des les identifier.

Par exemple, pour attacher un marker dont l’id est fleche, on fera : marker:url(#fleche);.

Il existe trois autre propriétés CSS qui permettent d’affiner le placement des marqueurs. Il s’agit des propriétés marker-start qui permet de spécifier le marqueur pour le point de départ du tracé, marker-end qui permet de spécifier le marqueur pour le dernier point du tracé, et marker-mid pour tous les autres points.

Enfin, sachez qu’on peut aussi utiliser les marqueurs avec les line, polyline et polygon.

Les attributs markerWidth, markerHeight et markerUnits.

Pour commencer, il faut préciser que le système d’unités dans les marqueurs est différents des autres éléments graphiques. En effet, ce ne sont pas les unités utilisateur qui sont utilisées, mais l’unité de base est la largeur de la bordure du chemin. Cette possibilité est très intéressantes : vous pouvez avoir des chemins de différentes largeurs, les dimensions des marqueurs resteront proportionnels à la largeur du chemin. Il est néanmoins possible de dire au processeur SVG qu’on ne veut pas utiliser comme unité la largeur du chemin, mais nos propres unités grâce à l’attribut markerUnits qu’on positionnera à userSpaceOnUse (la valeur par défaut est strokeWidth).
Les attributs markerWidth et markerHeight permettent respectivement de préciser la largeur et la hauteur du marqueur, selon l’unité de markerUnits. Si un de ces deux attributs n’est pas reneigné, il prendra 3 pour valeur. Exemple :

<]]> < Des marqueurs sur un chemin ]]>
Des marqueurs sur un chemin

À première vu, ça n’est pas ce qu’on pourrait espérer :S.

Les attributs refX, refY et orient.

La première chose à faire pour que nos flèches soient bien orientées serait de redéfinir le centre du dessin du marqueur. C’est à ça que servent les attributs refX et refY. Dans notre cas, il faudrait que le centre soit au point 0,2 :

<]]> < Des marqueurs sur un chemin : redéfinition du centre ]]>
Des marqueurs sur un chemin : redéfinition du centre

Rappellez vous qu’un des avantages des feuilles de style CSS externes est qu’on peut styler plusieurs document avec une seule feuille de style. C’est ce que nous venons de faire ici.

C’est déjà beaucoup mieux. Il ne reste plus qu’à orienter notre marqueur pour qu’il aille dans le sens du chemin grâce à l’attribut orient qui prend comme valeur un nombre représentant un angle en degrés, ou le mot-clé orient. C’est ce mot-clé qui nous intéresse :

<]]> < Des marqueurs sur un chemin : orientation automatique ]]>

Perfect :p. Les valeurs numériques peuvent être intéressantes le marqueur représente quelquechose de concret, un arbre par exemple, qui doit toujours être du même sens.

Le chapitre sur les chemins est maintenant terminé, mais vous allez vous rendre compte qu’on l’utilise beaucoup, notamment dans les animations (ce chapitre va réllement vous plaire, mais un peu de patience B)…) ou pour y mettre du texte. Tiens, j’ai dit texte ?

Comment bien structurer un document SVG
Le texte