# Découvrir le SVG/Manipulations avancées
## Réutilisation d'objets

Un objet peut être réutilisé, « cloné ». Il faut pour cela lui définir un attribut id (identité), c'est-à-dire lui donner un nom, une étiquette. On peut ensuite utiliser un élément use et faire référence à cet objet grâce à l'attribut href de l'espace de nom xlink.
L'exemple ci-dessous dessine un rectangle, puis en fait une copie située 60 px plus à droite.
On peut définir un objet sans le tracer pour ensuite le dupliquer. Cela se fait avec l'élément defs, qui s'utilise comme l'élément g. Les éléments defs devraient se trouver juste après la balise d'ouverture <svg … >. L'exemple suivant donne le même résultat que ci-dessus :
Ici, l'objet original a été défini à l'origine (0, 0), les attributs x et y de l'élément use deviennent donc des coordonnées absolues.
À la place de l'élément defs, on peut utiliser l'élément symbol qui fonctionne de la même manière. Les deux différences sont que :
* l'identifiant se met directement dans la balise, <symbol id="…"> … </symbol> ;
* lorsque l'on utilise un élément symbol, on crée une fenêtre (viewport) à l'intérieur de l'image ; on peut par exemple utiliser les attributs preserveAspectRatio et viewBox.

## Calques

De nombreux logiciels de dessin utilisent la notion de « calque » (layer). Un calque est un groupe de figures qui sont ensemble. Il faut imaginer un document comme une superposition de feuilles transparentes, chaque feuille transparente étant un calque. On peut typiquement changer l'ordre d'empilement des calques, certains dessins en cachant d'autres, et l'on peut rendre visible ou invisible un calque (par exemple afficher une grille ou la masquer).
En SVG, il n'y a pas de notion de calque, mais la notion de groupe (élément g) et de symbole (éléments symbol) sont équivalentes.
L'ordre des instructions dans le document indique l'ordre dans lequel les éléments sont dessinés ; ainsi, si l'on dessine deux éléments, le deuxième peut recouvrir le premier, le cacher. Ainsi, l'ordre des groupe correspond à l'ordre des calques, le premier groupe du document est le calque du bas et le dernier groupe est le calque du dessus. On peut changer l'ordre des calques en déplaçant les groupes dans le fichier.
Par ailleurs, un groupe peut posséder un attribut visibility qui permet de le masquer (valeur "hidden") ou de l'afficher (valeur "visible"). S'il s'agit d'un symbole ou d'un groupe mis dans un élément defs, l'attribut doit avoir la valeur "inherit" afin que s'applique la valeur définie dans l'appel use, par exemple :

## Transformations géométriques
### Attribut transform

Nous avons déjà présenté l'attribut transform précédemment, voir Éléments graphiques > Syntaxe générale et aspect des objets.Nous disposons également des transformations suivantes (les virgules peuvent être omises) :
* rotate(angle, cx, cy) : effectue une rotation de centre (cx, cy), les valeurs étant dans l'unité par défaut, et d'amplitude angle (en degrés par défaut) ;
* translate(tx, ty) : effectue une translation de vecteur (tx, ty) ;
* scale(s) : effectue une homothétie (changement d'échelle) de facteur s ;
* scale(sx, sy) : dilate d'un facteur sx selon l'axe des x et d'un facteur sy selon l'axe y ;
* skewX(angle) : incline l'image d'une quantité angle (en degrés par défaut) selon l'axe des x ;
* skewY(angle) : incline l'image d'une quantité angle (en degrés par défaut) selon l'axe des y ;
* matrix(a, b, c, d, e, f) : effectue l'application linéaire correspondant à la matrice de transformation ${\begin{pmatrix}a&c&e\\b&d&f\\0&0&1\end{pmatrix}}$.
Pour reprendre l'exemple ci-dessus, on pourrait écrire :
Concernant la transformation matricielle, si (x$_0$, y$_0$) sont les coordonnées avant transformation et (x$_1$, y$_1$) sont les coordonnées après transformation, on a :
    ${\begin{pmatrix}x_{1}\\y_{1}\\1\end{pmatrix}}={\begin{pmatrix}a&c&e\\b&d&f\\0&0&1\end{pmatrix}}\cdot {\begin{pmatrix}x_{0}\\y_{0}\\1\end{pmatrix}}$.
On a donc les équivalences :
    ${\mathtt {translate(tx,ty)}}\ :\ {\begin{pmatrix}1&0&tx\\0&1&ty\\0&0&1\end{pmatrix}},\ {\mathtt {matrix(1,0,0,1,tx,ty)}}$
    ${\mathtt {scale(sx,sy)}}\ :\ {\begin{pmatrix}sx&0&0\\0&sy&0\\0&0&1\end{pmatrix}},\ {\mathtt {matrix(sx,0,0,sy,0,0)}}$
    ${\mathtt {rotate(a)}}\ :\ {\begin{pmatrix}\cos a&-\sin a&0\\\sin a&\cos a&0\\0&0&1\end{pmatrix}},\ {\mathtt {matrix(\cos a,\sin a,-\sin a,\cos a,0,0)}}$
    ${\mathtt {skewX(a)}}\ :\ {\begin{pmatrix}1&\tan a&0\\0&1&0\\0&0&1\end{pmatrix}},\ {\mathtt {matrix(1,0,\tan a,1,0,0)}}$
    ${\mathtt {skewY(a)}}\ :\ {\begin{pmatrix}1&0&0\\\tan a&1&0\\0&0&1\end{pmatrix}},\ {\mathtt {matrix(1,\tan a,0,1,0,0)}}$
Quand une série de transformations est spécifiée, celles-ci sont appliquées de droite à gauche.
La séquence équivaut à l'arborescence ci-dessous : les éléments internes étant appliqués avant les éléments englobants.

### Exemple : création d'une courbe de Koch

La courbe de Koch est une courbe fractale qui peut se construire en répétant des opérations simples. Le code suivant a été proposé par User:Fibonacci sur Wikimedia Commons. Il consiste à tracer un trait horizontal de longueur arbitraire l$_0$ = 14 et de lui attribuer l'étiquette it0 :
On remarque ici que l'on a par défaut x$_1$ = 0, y$_1$ = 0, y$_2$ = 0.
Cet objet est ensuite translaté de cette même longueur l$_0$ = 14 puis tourné de –60 ° ; le tout est mis dans un groupe portant l'identifiant it1 :
Cet objet it1 est à son tour dupliqué, translaté d'une longueur 3 × l$_0$ = 42 et retourné horizontalement par la commande scale(-1, 1). Le tout est mis dans un groupe portant l'identifiant it2. Et ainsi de suite ; comme on a six étapes récursives, la dernière translation se fait d'une longueur 3$^6$ × l$_0$ = 10 206. L'ensemble est ensuite ramené à une échelle permettant de tenir dans la fenêtre de 621 × 180. Le code complet est donc :

### Fenêtre (viewport)

Certains éléments créent une fenêtre (viewport) : svg (crée la fenêtre cadre), symbol (voir ci-dessus), image et foreignObject.
Les limites de cette fenêtre peuvent être définis, comme indiqué précédemment, par les attributs x, y, width et height (voir Structure d'un fichier SVG > Les attributs de l'élément svg). Cela permet de translater l'objet et le cas échéant de lui appliquer un facteur d'échelle, en fonction de la valeur de l'attribut preserveAspectRatio (ibid.).
L'attribut viewBox permet de définir un repère à l'intérieur de cette fenêtre : la syntaxe
    viewBox="xmin, ymin, largeur, hauteur"
indique que le point en haut à gauche aura les coordonnées (xmin, ymin) et que le point en bas à droite les coordonnées (xmin + largeur, ymin + hauteur). Notez que les virgules ne sont pas obligatoires.
Ainsi, nous reprenons l'exemple ci-dessous mais en utilisant l'attribut viewBox pour avoir des valeurs de coordonnées et de longueur en centimètres plutôt qu'en pixels. Notez qu'il faut redéfinir l'épaisseur de trait par défaut (nous prenons ici une épaisseur unité de 0,03 cm).

## Apparence des éléments
### Marqueurs

Un marqueur est un symbole graphique qui s'affiche au milieu ou à l'extrémité d'une ligne : triangle (pointe de flèche), carré, disque… On peut ainsi créer un élément marker et l'utiliser dans un élément path, line, polyline ou polygon.
L'élément marker est un « conteneur », à l'image d'un élément g, qui possède un identifiant (attribut id). Lorsque l'on dessine la courbe (donc dans l'élément path, line…), on place alors un attribut marker-start (marqueur en début de ligne), marker-mid (milieu) ou marker-end (marqueur en fin de ligne) avec la valeur "url(#identifiant)".
Par exemple, si l'on désire mettre un disque à chaque extrémité de la ligne, on peut écrire :
mais le résultat obtenu n'est probablement pas celui attendu :
* le disque n'est pas centré sur l'extrémité de la ligne mais est décalé ;
* le disque est très petit et si vous augmentez le rayon, vous obtenez un carré à la place.
En effet, le marqueur est affiché dans une fenêtre (viewport) dont la taille est proportionnelle à la largeur du trait de la courbe (ici 5 px) et de dimension 3 × 3 par défaut (c'est-à-dire un carré faisant trois fois l'épaisseur de la ligne).
Le code suivant est plus satisfaisant :
Les attributs :
* markerWidth et markerHeight définissent une fenêtre de 5 × 5 (par rapport à l'épaisseur du trait) ;
* refX et refY décalent la fenêtre de ses demi-dimensions afin qu'elle soit centrée sur l'extrémité de la ligne.
Le cercle est ensuite placé au centre de la fenêtre et son rayon est choisi pour qu'il soit inscrit dans la fenêtre ; si l'on trace le périmètre (on définit une couleur par le paramètre stroke), il faut ajuster le rayon pour que l'épaisseur du trait soit contenue dans la fenêtre.
Le code suivant permet de placer des traits d'arrêt perpendiculaires à la ligne :
Nous avons utilisé l'attribut orient="auto" qui permet d'aligner les axes du repère de la fenêtre du marqueur avec la direction locale de la ligne. On peut à la place indiquer une valeur numérique, il s'agit alors de l'angle duquel est tournée la fenêtre par rapport au la page (et non pas par rapport à la direction de la courbe).
Voici un exemple complet :
Ce code est un extrait de l'image Fichier:Trame isometrique.svg.

### Transparence

Les différents objets graphiques peuvent posséder un attribut fill-opacity dont la valeur peut être :
* un nombre entre 0 et 1 : fill-opacity="0" indique un élément totalement transparent, fill-opacity="1" indique un élément totalement opaque (valeur par défaut) ;
* la valeur fill-opacity="inherit" : typiquement pour un objet « cloné » par un élément use, utilise l'opacité définie dans l'élémznt use.

### Dégradés de couleurs

En SVG, on peut définir deux types de dégradés de couleur : les dégradés linéaires — la couleur change lorsque l'on se déplace dans une direction — et les dégradés radiaux — la couleur change lorsque l'on s'éloigne d'un point.
Un dégradé est représenté par un identifiant. Il peut être appliqué pour le remplissage d'un objet, avec la syntaxe fill="url(#identifiant)", ou à son trait avec la syntaxe stroke="url(#identifiant)".
Le dégradé peut se représenter comme une échelle de couleurs. Les couleurs de référence sont appelées « arrêts » (stops) et sont caractérisés par :
* leur position sur l'échelle (offset) ;
* la nature de la couleur.
Ainsi, les gradients contiennent au moins deux éléments stop ayant pour attributs :
* offset : nombre entre 0 et 1, ou bien pourcentage, désignant la position dans l'échelle ; le bas de l'échelle est désigné par offset="0" ou bien offset="0%", le haut de l'échelle est désigné par offset="1" ou bien offset="100%" ;
* stop-color : couleur habituelle, par exemple stop-color="black" ou bien stop-color="#000000" (voir Éléments graphiques > Syntaxe générale et aspect des objets) ;
* le cas échéant stop-opacity qui définit l'opacité de l'arrêt (voir ci-dessus).

#### Dégradé linéaire

Un dégradé linéaire est défini par un élément linearGradient. Cet élément est entre les balises defs en début de document est possède un identifiant (attribut id). L'exemple suivant définit un dégradé du bleu au rouge et l'applique à un rectangle :
On peut également définir le vecteur du gradient sous la forme de quatre attributs x1, y1, x2 et y2 : les arrêts à 0 % et à 100 % sont placés respectivement aux points P$_1$(x$_1$, y$_1$) et P$_2$(x$_2$, y$_2$), et les ligne de même couleur sont perpendiculaires à la droite (P$_1$P$_2$). Par exemple, le code suivant fait un dégradé suivant la grande diagonale du rectangle :
L'élément peut contenir un attribut gradientTransform qui fonctionne de la même manière que l'attribut transform des objets graphiques (voir ci-dessus). Cela permet par exemple d'incliner (skew) le dégradé.
Enfin, l'attribut spreadMethod définit ce qui se passe si l'objet est plus étendu que le dégradé (c'est-à-dire si le vecteur gradient ne couvre pas les abscisses et les ordonnées de 0 à 100 % de l'objet) :
* spreadMethod="pad" : les couleurs aux extrêmes sont étendues jusqu'aux bords de l'objet ;
* spreadMethod="reflect" : le dégradé part dans l'autre sens ;
* spreadMethod="repeat" : le dégradé recommence, il se répète.

#### Dégradé radial

Un dégradé radial s'obtient avec l'élément radialGradient. Les attributs spécifiques sont :
* cx, cy et r : paramètre du disque contenant le dégradé ; l'arrêt à 100 % se situe sur le périmètre du cercle de centre (cx, cy) et de rayon r ; par défaut, le disque est le plus petit disque contenant l'objet (c'est-à-dire que cx = cy = r = 50 %) ;
* fx, fy : coordonnées du foyer du dégradé ; l'arrêt à 0 % se situe au point de coordonnées (fx, fy) ; par défaut, ce point se situe au centre du disque (fx = cx, fy = cy).
On dispose également des attributs gradientTransform et spreadMethod.
Par exemple :

### Motifs

Il est possible de remplir une surface par un motif.
Un motif est un dessin inclus entre les balises d'un élément pattern. Il s'utilise de la même manière qu'un dégradé.
Par exemple, si l'on veut remplir une surface par des disques bleus :
Les paramètres width et height demandent quelques explications. Par défaut, la valeur 1 désigne la dimension totale de l'objet à remplir (largeur totale pour width, hauteur totale pour height). En mettant les valeurs 0.1, nous indiquons que le motif est répété tous les 0,1 dans l'unité locale, c'est-à-dire tous les 1/10 de la largeur et de la hauteur ; cela affiche donc 10 motif dans le sens de la hauteur et 10 motifs dans le sens de la largeur, soit 100 disque sur la surface.
Cette situation peut poser problème : en effet, la taille et les proportions largeur/hauteur du motif dépendent des dimensions de l'objet alors que l'on voudra sans doute que le motif apparaisse tel que dessiné.
On peut indiquer des dimensions « classiques » avec l'attribut patternUnits="userSpaceOnUse" : les valeurs indiquées dans les attributs width et height sont alors la largeur et la hauteur du rectangle dans lequel le motif est dessiné, et la surface est ensuite pavée par ces rectangles. Les dimensins du motif sont alors indépendantes des dimensions de l'objet. Par exemple :
Les motifs s'appliquent également aux contours.
Voir aussi : commons:Category:SVG patterns.

### Traits et pointillés

Les éléments à une dimension — chemins (path), segments de droite (line), polygones (polyline) — disposent d'un paramètre stroke-dasharray. Il s'ensuit une liste de nombres séparés par des virgules, qui correspondent à la longueur des segments et des espaces vides. Les nombres peuvent être des longueurs — avec une unité (mm, in, px) ou sans unité pour l'unité par défaut — ou bien des pourcentages — % —, il s'agit alors du pourcentage de la taille de l'image ou de la boîte englobante (dégradé, motif, masque, filtre).
Exemple
Pour un trait mixte (alternance trait long-trait court) :

### Animation

Le langage SVG dispose d'éléments permettant des faire des animations$^,$, essentiellement les éléments animate et animateTransform. Il faut pour cela que le navigateur gère ces éléments ; c'est le cas de d'Opera, Firefox, Safari et Chrome.
Les éléments graphiques sont définis par des paramètres numériques (position, taille…). L'élément animate permet de modifier les valeurs de manière continue durant une certaine durée. La syntaxe globale est :
Elle concerne son parent direct. Par exemple, si l'on veut changer la position d'un rectangle, on écrit :
le rectangle va ainsi passer de la position x = 0 à x = 10 en cinq secondes. Vous remarquerez que la balise rect a été coupée en deux : <rect…> … </rect…> au lieu de la balise unique <rect… /> habituelle.
Dans l'élément animate, l'attribut fill indique le comportement lorsque l'animation touche à sa fin : "freeze" pour que l'objet reste dans son état final, "remove" pour qu'il revienne à son état initial.
Si l'on veut modifier un paramètre de l'attribut transform, on utilise l'élément animateTransform.
Exemple complet :
Voir le résultat.
Plutôt que de mettre l'élément animate entre les balises ouvrantes et fermantes de l'élément graphique, on peut aussi y faire référence avec un attribut xlink:href, par exemple :

## Utilisation de styles

Les styles permettent de définir des paramètres par défaut. Lorsque plusieurs objets utilisent les mêmes paramètres (couleur de remplissage, couleur de trait, épaisseur de trait…), il est utile de définir un style. Ainsi, lorsque l'o change le style, cela change l'affichage pour tous les objets, donc :
* cela permet des changement faciles et rapide même lorsqu'il y a de nombreux objets ;
* cela assure une homogénéité au sein du document voire entre les documents (dans le cas d'un feuille de style extérieure) ;
* cela évite les erreurs : une erreur affectant plusieurs objets, elle est repérée beaucoup plus vite.

### Style au format CSS

    Pour plus de détails voir : Le langage CSS.

#### Feuille de style externe

On peut avoir recours à une feuille de style externe, sous la forme d'un fichier .css. Par exemple
Fichier monstyle.css
Fichier mondessin.svg
Dans le fichier CSS, nous définissons le style par défaut des éléments rect.
Dans le fichier SVG, nous avons ajouté une référence à la feuille de style : <?xml-stylesheet href="mystyle.css" type="text/css"?>.

#### Styles définis dans le fichier SVG

Les styles peuvent être déclarés à l'intérieur du fichier SVG, soit en en-tête, soit dans l'élément lui-même — mais alors le CSS présente peu d'intérêt.
En en-tête du fichier
Dans l'élément

#### Classes

On peut définir des classes, c'est-à-dire des styles différenciés. Par exemple :
ou encore :

#### Passage de la souris

L'exemple suivant permet de modifier l'apparence d'objets lorsque le pointeur de la souris survole l'objet (hover).
Fichier SVG :
Fichier CSS :

### Style au format XSL

Le XSL est un langage permettant de transformer automatiquement du XML, et donc par conséquent du SVG. On peut ainsi utiliser le XSL pour indiquer d'ajouter systématiquement les attributs fill="red" stroke="blue" stroke-width="3" aux éléments SVG rect.
On crée pour cela un fichier monstyle.xsl contenant
puis on ajoute dans l'en-tête du fichier SVG :
    Pour plus de détails voir : Programmation XML/XSLT et Programmation XML/XSL-FO.

## Métadonnées

Les métadonnées (metadata) sont des informations sur le fichier lui-même. La présence de métadonnées facilite le traitement automatique des données, par exemple leur recensement, leur catégorisation. Le W3C a développé une norme appelée RDF (resource description framework) et sa mise en œuvre dans le XML.
L'intégration de métadonnées nécessite de déclarer les espaces de nom rdf auquel nous ajoutons rdfs (RDF schema) et dc (Dublin core) qui fournissent une syntaxe.
Si l'on veut ajouter des informations sur la licence, on peut déclarer l'espace de nom c (Creative Commons) :

## Liens

L'élément a permet de rendre un objet cliquable, le clic menant vers une adresse donnée. L'objet est encapsulé entre des balises <a xlink:href="…"> … </a…>. Par exemple :

## Notes

* ↑ « Animation (SVG 1.1) », sur W3C (consulté le 1er décembre 2018)
* ↑ « SVG animations », sur SVG WG (consulté le 1er décembre 2018)
* ↑ (en) Jeremie Patonnier, « Re: Good place to be asking non FF SVG questions? », sur Mozilla FireFox dev-tech-svg mailing list sur Google Groupes, 31 août 2017 (consulté le 1er septembre 2017)
Chemins < ↑ > Le SVG pour l'enseignement