Accueil

Traduction

Dessiner avec SVG - sommaire

Dessiner avec SVG - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

SVG - Les formes de base

Dans ce chapitre je vais vous montrer comment encoder directement en SVG dans une page web pour dessiner :

Vous allez constater que le langage SVG ressemble beaucoup au langage HTML. Vous retrouvez des instructions construites à partir d'une balise suivie d'attributs dont style et class. Ce qui signifie que vous pouvez styler les formes SVG via le CSS.

La feuille de style de la page

Pour info la feuille de style interne de cette page :

...
svg{display : block ; margin : 10px auto; border : 1px solid black}
rect.joli {fill : red; fill-opacity : 0.5 ; stroke-width : 10; 
	stroke : green; stroke-opacity : 0.5 ;}
...

Je définis deux règles de style relatives à l'élément SVG et une autre pour les éléments RECT affectés de la classe "joli".
SVG est un élément du langage HTML5.
Par contre RECT est un élément du langage SVG.

Dessiner des rectangles

Comment se repérer dans une zone de dessin SVG

L'élément SVG définit un repère cartésien dont les caractéristiques sont établies par l'attribut viewBox (OU à défaut par les attributs width & height).
Attention l'origine du repère cartésien est situé en haut à gauche !

Deux rectangles dessinés dans un canevas SVG

Code correspondant

Dans une page web, le code SVG doit être contenu à l'intérieur du conteneur SVG.

Pour dessiner un rectangle il faut utiliser l'élément rect avec les attributs x,y, width & height.
Les attributs x & y indiquent les coordonnées du coin supérieur gauche du rectangle.
Comme je ne précise la couleur de remplissage, les rectangles sont remplis de noir (couleur par défaut).

Concernant le deuxième rectangle, les angles sont arrondis car il y a deux attributs supplémentaires :
rx & ry : rayon horizontal et rayon vertical de chaque arrondi.
Si un seul de ces attributs est précisé, ils sont supposés être égaux (rx = ry).

Remarquez que la balise SVG contient l'attribut viewBox et que la valeur de l'attribut width est un pourcentage (50%).
Ce qui signifie que l'on définit un repère cartésien de 400 par 200 qui sera affiché dans la page web avec une largeur égale à 50% de celle de son conteneur (élément BODY).
Quand à la hauteur de la zone de dessin elle sera toujours égale à la moitié de la largeur d'affichage ; Le ratio largeur/hauteur étant défini par le viewBox.

Retenez : les positions et dimensions des formes sont déterminées via l'attribut viewBox OU à défaut par les attributs width & height si l'attribut viewBox est absent.

Deux rectangles dessinés - variante

Code SVG correspondant

Le code SVG est identique sauf ajout de ... class ="joli" ... donc je style les rectangles avec les paramètres de présentation de la classe "joli".
Sous SVG les paramètres de présentation peuvent être passés en propriétés CSS ou en attributs.
J'aurais pu écrire :

Avant de coder

"Sans méthode la pensée erre et l'action tâtonne"

Rappel : dans un canevas SVG le point d'origine du repère cartésien est le coin haut gauche. svg croquis

Si vous voulez être productif (coder vite et bien) je vous conseille de passer par le stade croquis sur une feuille de papier millimétrée (ou une feuille à petit carreaux) avant de vouloir coder en SVG.

La syntaxe SVG

La balise SVG est obligatoirement double (une balise début et une balise fin) et délimite le code SVG.

Dans le cadre de SVG interne (code SVG inclus dans une page web) la balise SVG est un élément HTML (et non pas un élément SVG). On ne peut donc pas lui appliquer les paramètres de présentation spécifiques aux éléments SVG tels fill, stroke, etc. Mais on peut lui applquer les propriétés CSS de toute boite HTML : background, border, box-shadow, etc.

Ces éléments sont tantôt des balises simples et tantôt des balises doubles.
Un élément de forme est obligatoirement une balise double s'il contient un autre élément. Cette situation est fréquente en cas d'animation d'un objet ; vous avez alors la syntaxe suivante :

Ici l'élément circle contient l'élément animate donc la balise circle est double.

Si l'élément de forme ne contient aucune autre élément, il s'agit alors d'une balise simple mais bien fermée comme dans l'exemple ci-dessous :

L'élement rect est ici une balise simple mais bien fermée : une barre oblique avant la parenthèse angulaire fermante.

Dessiner des cercles

Exemple

cercles avec SVG - balise circle

le code SVG correspondant

L'attribut viewBox est absent donc les caractéristiques du repère cartésien sont définies par les attributs width & height (exprimés alors de façon implicite en pixels).
La zone de dessin s'affichera toujours avec 400 pixels de large et 200 de haut quelque soit l'écran, donc ce canevas n'est pas "responsive" !

Pour dessiner un cercle il faut utiliser l'élément circle :

Nous avons à cette fin utiliser les paramètres de présentation sous forme d'attributs sauf pour le quatrième cercle où nous avons passés ces paramètres sous forme de propriétés.

En SVG les paramètres de présentation peuvent être passés en attributs OU en propriétés CSS.
Par contre les paramètres géométriques (r,width,height,cx,cy,x,y,rx,ry) doivent impérativement être manipulés en tant qu'attributs de balise.
Dans le cadre de la version 2 de SVG il est prévu que tous les paramètres pourront être passés indifféremment en attributs ou en propriétés CSS.
Seul le navigateur Chrome prend en compte à ce jour cette simplification notable de la syntaxe SVG.

Pour les paramètres fill-opacity, stroke-opacity la valeur va de 1 (opacité totale) à 0 (transparence totale).

Attention si vous dessinez un cercle de rayon 40 pixels dont l'épaisseur du contour est 10 pixels le rayon total du rond sera 45px ! En effet le contour est à la moitié à l'intérieur de la forme et à moitié à l'extérieur de la forme.

Styler les formes SVG

Si vous souhaitez que tous les cercles aient le même style vous pouvez bien sûr créer une règle CSS relative au sélecteur "circle" dans la feuille de style interne de la page :

...
// styler les éléments HTML
body {...
h1,h2 {...
img {...
svg {...

// styler les éléments SVG
circle {fill : green ; stroke-width : 5px ; stroke : red ; }
rect {fill : ...
line {...}
...

Vous pouvez aussi définir des classes génériques ou spécifiques à un type d'élément.

...
circle.style1 {fill : ... ; stroke : ...}
circle.style2 {fill : ... ; stroke : ...}
.ukraine {fill : yellow ; stroke : blue ; ...}
...

Vous devrez alors écrire dans le conteneur SVG :

Attention les propriétés background, border, box-shadow, etc. ne s'appliquent qu'à des éléments HTML mais jamais à des éléments SVG.
Je rappelle que l'élément SVG est une balise HTML (et non pas un élément du langage SVG).

Dessiner des ellipses

Premier exemple

Le code SVG correspondant

Deuxième exemple

Une ellipse qui ressemble à un cercle.

Affichage satisfaisant sur tous les écrans ; la zone de dessin a toujours une largeur de 50% de celle du conteneur.
Notez que le canevas SVG a une couleur de fond et est ombré.

Le code SVG correspondant

La zone de dessin est "responsive" (width ="50%") ; l'attribut viewBox est alors obligatoire.

Notez aussi que j'ai utilisé la balise ellipse pour représenter un cercle ... Et oui, un cercle est en fait une forme particulière d'ellipse : rx = ry.

Dessiner segments et polygones

Dessiner des segments

Lignes avec SVG - balise line

Le code correspondant

La zone de dessin est "responsive" (widht ="60%").
L'attribut viewBox est alors obligatoire.

Pour tracer un segment il faut employer la balise line avec 4 attributs : abscisse et ordonnée (x1 et y1) du point de départ puis abscisse et ordonnée du point d'arrivée (x2 et y2).
Par défaut une ligne a une épaisseur de 1 pixel(voir première ligne).
L'attribut stroke-linecap avec la valeur round permet d'avoir des extrémités arrondies (ajout d'un demi-cercle à chaque extrémité) et l'attribut stroke-dasharray avec la valeur 5 5 permet d'avoir des lignes pointillées : 5 pixels coloriés puis un intervalle de 5 pixels

Pour l'attribut stroke-linecap les autres valeurs possibles sont butt (valeur par défaut) et square (ajout d'un carré à chaque extrémité de la ligne).

Pour l'attribut stroke-dasharray le nombre d'arguments n'est pas forcément limité à 2 mais doit être pair. Par exemple : stroke-dasharray = '5 5 10 10' qui veut dire : un trait de 5 pixels puis un blanc de 5 suivi d'un trait de 10 et un espace de 10. Ce motif répété sur toute la ligne !

Notez que dans l'exemple le formatage d'un trait est tantôt réalisé sous forme d'attributs et tantôt sous forme de propriétés.

Élements polygon & polyline

Pour dessiner des polygones ouverts ou fermés on utilise ces deux balises du langage SVG. La balise polygon rajoute automatiquement un segment entre le dernier et le premier point

Dans le premier triangle les angles sont arrondis, "aiguisés" dans le deuxième triangle et tronqués dans la troisième forme.

Le code correspondant

La zone de dessin est "responsive" (widht ="60%").
L'attribut viewBox est alors obligatoire.

On emploie donc la balise polygon pour dessiner une ligne brisée fermée et la balise polyline pour dessiner une ligne brisée ouverte.
Ces deux balises sont très proches ; la seule différence est que la balise polygon ajoute automatiquement un segment entre le dernier et le premier point. Pour ces deux balises il suffit de préciser les coordonnées x et y des différents angles.
Notez bien la syntaxe : x,y x,y x,y ...

Remarquez que le premier et troisième triangles sont remplis de noir car j'ai oublié l'attribut fill = "none". Donc par défaut l'objet est remplie de noir.

Notez l'emploi du paramètre stroke-linejoin pour préciser le style des angles.

Il s'agit d'un paramètre de présentation, il aurait pu être passé en propriété CSS.

L'attribut fill-rule

Rappel : il s'agit de paramètres de présentation et peuvent donc être manipulés comme des proprités CSS.

Rôle de fill-rule

Le paramètre fill-rule règlé à "evenodd" ne remplit que les zones extérieures de la forme.
Cette situation se produit uniquement pour les formes dont des segments se coupent.

Exemples

Une étoile entièrement remplie de vert clair

Le code correspondant :

Une étoile partiellement remplie

Le coeur de l'étoile n'est pas remplie ...
Le code correspondant : c'est exactement le même code que précédemment sauf que la valeur de fill-rule est désormais "evenodd".

Remarque

La valeur par défaut de l'attribut fill-rule est "nonzero"
Donc pour remplir totalement l'étoile j'aurais pu faire abstraction de cet attribut.

Votre navigateur a t-il implémenté la version 2 de SVG ?

Dans le cadre de la version 2 de SVG il est prévu entre autres, que les paramètres géométriques (de taille et de position) puissent être passés en propriétés CSS (comme les paramètres de présentation).

Exemple de code en SVG version 2

On pourra alors écrire :

Dans le code ci-desssus non seulement les paramètres de présentation mais aussi les paramètres géométriques sont passés sous forme de propriétés (via l'attribut style).
Notez que j'ai écrit fill-rule : evenodd.
Donc via un "keyframes" (modèle d'animation CSS) on pourra modifier les paramètres de présentation mais aussi les paramètres géométriques alors qu'avec la version 1 on est obligé d'animer les paramètres géométriques en SMIL ou JS.

Le rendu

Si aucune forme n'apparait dans le canevas c'est que votre navigateur n'a pas encore implémenté SVG 2.
À ma connaissance, ce code ne fonctionne à ce jour (juin 2025) qu'avec Chrome.
Remarque : si vous avez visionné avec Chrome vous constatez que fill-rule : evenodd n'a aucun impact sur une forme simple (pas de segments qui se coupent).

Simplifiez le code par des regroupements

Je vais maintenant aborder l'élément G (G comme grouper).

Un code inutilement complexe

Le canevas

Le code correspondant

Les deux formes ont exactement les mêmes attributs de présentation !

Le code simplifié

Le canevas

Le code correspondant

Les deux formes ont été regroupées à l'intérieur du conteneur G.
L'élément G peut contenir des attributs dont style avec des propriétés de présentation.
Le paramètre opacity remplace les attributs fill-opacity & stroke-opacity

Pourquoi effectuer des regroupements ?

Le regroupement de formes (conteneur G) permet de simplifier le code lorsque ces formes ont des paramètres de présentation identiques.

Comment afficher / masquer une forme (un groupe de formes) ?

Il s'agit de paramètres de présentation ; ils peuvent être passés en propriétés.

Exemple

Ci-dessous un canevas avec trois groupes de formmes :

Le deuxième groupe n'apparait pas !

Le code correspondant

Une animation basée un paramètre d'affichage / masquage

Ce tuto comprend plusieurs chapitres sur les dessins SVG animés (à partir du chapitre 10).
Mais je ne me m'empécher de faire une digression pour vous montrer déjà l'importance des paramètres opacity, visibility, display dans le cadre des animation SVG.

Un calque ou "couche" est un groupes logique d'objets d'un canevas.
Un canevas peut comprendre plusieurs "couches" qui se superposent.
En masquant / démasquant une couche on modifie l'aspect d'un dessin vectoriel.
Masquer / démasquer un calque est à la base de l'animation SVG.

Le canevas vide par défaut

Le code HTML & SVG

Le code SVG réparti entre deux calques : "jour" & "nuit" qui sont tous deux masqués mais via des paramètres différents : visibility pour le premier et display pour le deuxième calque.

Notez l'astuce pour dessiner le clair de lune : un cercle "navy" (couleur du ciel, la nuit) recouvre partiellement le rond jaune. Il aurait été beaucoup plus délicat d'encoder un arc de cercle et un arc d'ellipse ...

Deux boutons de commande ; chaque bouton relié à une fonction anonyme.

Le script

En effet l'animation qui consiste à masquer l'un des calques et afficher l'autre est réalisée via JS.

document.querySelector("#bouton1").onclick = function ()
{
	document.querySelector("#jour").style.visibility ="visible";
	document.querySelector("#nuit").style.display ="none";
}
document.querySelector("#bouton2").onclick = function ()
{
	document.querySelector("#nuit").style.display ="inline";
	document.querySelector("#jour").style.visibility ="hidden";
}

Deux fonctions anonymes !
Je masque / démasque le premier calque via la propriété visibility et le deuxième calque via la propriété display.