Creer des images SVG

Le format svg


Le format SVG est un format ouvert de dessin vectoriel dérivé du xml.

Ce format est ouvert, c'est à dire que ces spécifications sont publiques et documentées et son utilisation n'est pas verouillée par un quelconque brevet ( contrairement au format gif par exemple ).

Il permet de faire du dessin vectoriel ; c'est à dire des combinaisons de formes définies de manière géométrique et du texte. Ceci par opposition aux formats bitmaps, tels que les photos numérisées. ( Toutefois, on peut inclure un fichier bitmap comme élément dans un dessin vectoriel ). Pour plus d'information sur les formats bitmaps et vectoriels, voir par exemple l'explication sur le site de l'académie d'Amiens

Ce format est dérivé du langage xml : c'est un langage à balises proche du html, autrement dit dans une certaine mesure le format est "intelligible" quand on le lit dans un éditeur de texte quelconque.

Préparatifs : logiciels requis

Visionner des images SVG

Plusieurs logiciels permettent de visionner les images SVG ; entre autres la visionneuse svg d'Adobe , la visionneuse SVG de Corel,  le navigateur du W3c Amaya, le projet Mozilla + svg.

Tous ces logiciels ne prennent pas en charge de manière égale toutes les énormes possibilités qu'offre ce langage ; aucun ne les gère toutes. Il semblerait que le logiciel le plus complet actuellement soit la visionneuse svg d'Adobe , qui s'installe sous windows comme un plugin de Internet Explorer ( beurk !... ).

Créer des images SVG

Le langage SVG a la particularité d'être "intelligible" ; on peut utiliser un simple éditeur de texte pour créer des images SVG !... Si vous lancez dans cette expérience (ce que je vous propose dans le chapitre suivant ), je vous conseille l'éditeur multifonction scite, disponible sous les plateformes Linux et Windows.

Sinon, certains logiciels de dessin vectoriels sont capable d'enregistrer, importer ou exporter au format svg. Une mention particulière pour le logiciel libre sodipodi, qui utilise svg comme format natif de travail, et qui est disponible pour les plateformes Linux et Windows.

Structure d'un fichier svg

J'ai testé avec la visionneuse svg d'Adobe les exemples que je vais décrire ci-dessous. Les fichiers SVG s'affichent alors dans Internet Explorer ( beurk !... ).
J'aurais préféré utiliser la solution multiplateforme mozilla+svg, mais apparemment les définitions d'éléments ( cf chapitre ci-dessous ) ne sont pas gérées.

Un document svg très simple

Dans un éditeur quelconque tapez (ou copiez-collez) les lignes suivantes :

<?xml version="1.0" encoding="iso-8859-1"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
 <circle cx="100" cy="20" r="10" />
 <rect x="80" y="30" width="40" height="10" />
</svg>

Cela peut paraître un peu barbare, mais on devine que cette figure contient un cercle et un rectangle.
Enregistrez le fichier sous le nom "essai1.svg", et visualisez le résultat. Vous devez obtenir une image comme celle ci-dessous :

simple 1

Si vous avez la flemme de créer ce fichier, essayez avec mon fichier essai1.svg

Structure d'un document xml

Analysons maintenant la structure du fichier :

La première ligne du document indique que le contenu qui suit est du "xml" :
<?xml version="1.0" encoding="iso-8859-1"?>

Mais qu'est-ce que c'est donc que le xml ??
Ce sont les initiales de "eXtended Markup Language", soit en français "Langage à Balises Etendu".

Ok, mais alors qu'est-ce que c'est que ces "balises" ??
Une balise est un élément qui est encadré par un symbole "<" et par un symbole ">".
Si l'on regarde notre fichier, on voit alors clairement plusieurs balises :

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"> est une balise
<circle cx="100" cy="20" r="10" /> est une balise
<rect x="80" y="30" width="40" height="10" /> est une balise
</svg> est une balise

En xml, il y a deux types de balises :
Voilà tout ce que vous avez besoin de savoir sur le langage xml pour le moment.

En résumé, un document svg a la structure suivante :

<?xml ... ?>
<svg ... >
    ....éléments du graphique
</svg>


.. où les  "éléments du graphiques" sont des balises xml décrivant des cercles, des rectangles etc...

Grouper des éléments

Une possibilité offerte par le svg est de grouper des éléments. Pour cela on doit les placer entre la paire de balise <g ... > et </g>. Par exemple :

<g>
 <circle cx="0" cy="-10" r="10" />
 <rect x="-20" y="0" width="40" height="10" />
</g>

On ainsi regroupé ainsi un cercle et un rectangle. Vous comprendrez par la suite l'intérêts de grouper des éléments.

Définir des éléments

Le langage SVG permet également de définir des éléments, pour les réutiliser ensuite. La paire de balise <defs> et </defs> sert à accueillir les définitions, qui pourront être utilisé dans le graphique au moyen de la balise <use.. />

Schématiquement, cela ressemble à peu près à cela :

<?xml ... ?>
<svg ... >
 <defs>
    < ... id="toto" >
    < ... id="titi" >
 </defs>
  ....
 <use xlink:href="#toto" ... />
    ...
 <use xlink:href="#toto" ... />
 <use xlink:href="#titi" ... />
</svg>


Pour prendre un exemple concret, voici comment on peut définir et réutiliser le groupe cercle et rectangle que nous avons créé précédemment :

<?xml version="1.0" encoding="iso-8859-1"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
 <defs>
   <g id="mongroupe">
     <circle cx="0" cy="-10" r="10" />
     <rect x="-20" y="0" width="40" height="10" />
   </g>
 </defs>
 <use xlink:href="#mongroupe" x="50" y="100"/> 
 <use xlink:href="#mongroupe" x="100" y="100"/>
 <use xlink:href="#mongroupe" x="150" y="100"/> 
</svg>


On obtient ainsi, comme résultat, le groupe cercle-rectangle répété trois fois, à des emplacements différents :

essai 2

Essayez en créant votre propre fichier, ou en utilisant mon fichier essai2.svg

Transformations

Le langage svg permet également d'effectuer des transformations géométriques sur des élements : translations rotations, ou transformations plus complexes.

Essayons par exemple d'effectuer une rotation de 60° sur le groupement défini précédemment :

<?xml version="1.0" encoding="iso-8859-1"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
 <defs>
   <g id="mongroupe" transform="rotate(60)">
     <circle cx="0" cy="-10" r="10" />
     <rect x="-20" y="0" width="40" height="10" />
   </g>
 </defs>
 <use xlink:href="#mongroupe" x="50" y="100"/> 
 <use xlink:href="#mongroupe" x="100" y="100"/>
 <use xlink:href="#mongroupe" x="150" y="100"/> 
</svg>


Voici le résultat :

essai 3

et le fichier correspondant : essai3.svg

Vous connaissez maintenant les bases du langages SVG : nous pouvons passer à quelque chose de plus consistant !...

Réalisation d'un plateau de dames chinoises

Pour montrer l'efficacité et la simplicité du langage SVG, je vais vous montrer comment, en quelques lignes, on peut réaliser une figure. Nous allons réaliser un plateau de dames chinoises ( encore appelé "jeu de l'étoile" ).

Relever les symétries et répétitions

Voici l'allure d'un plateau de dames chinoises :

analyse 1

Aïe ! Nous faudra-t-il vraiment décrire ce plateau cercle après cercle ? Bien sur que non, cela serait très fastidieux : nous allons essayer d'économiser le code SVG au maximum en utilisant les symétries et répétitions de motifs.

Ainsi, on peut remarquer dans ce plateau une répétition d'assemblages triangulaires de 10 cercles :

analyse 2

( il ne faudra pas oublier le cercle isolé au centre du plateau )


Dans ce groupe triangulaire de 10 cercles, on peut trouver encore une répétition d'assemblages triangulaires de 3 cercles :

analyse 3

( là encore il ne faudra pas oublier le cercle isolé au centre )

Nous allons choisir par exemple une hauteur de 30 pixels pour les petits triangles représentés ci-dessus. Cette dimension va nous servir de référence pour la suite. Le centre du sommet est situé aux 2/3 de la base, c'est à dire à 20 unités de chaque sommet. Si l'on veut que les cercles se touchent, leur diametre devra être un peu moins de 30 / cos(30°) soit environ 17 unités, disons 16 pour tenir compte de l'épaisseur des tracés.

Voilà donc le puzzle démonté... nous allons maintenant le remonter en utilisant le langage svg.

Construction

On commence par définir l'élément de base, qui sera un cercle de rayon 16 :
<circle id="1_cercle" cx="0" cy="0" r="16" />
etoile1
cx et cy désignent les coordonnées du centre du cercle. Pour se repérer, nous utiliserons toujours une croix rouge pour matérialiser le centre du repère, de coordonnées 0, 0.


Nous allons alors décaler ce cercle de 20 unités vers le haut avant de faire la rotation. L'axe des y est orienté vers le bas, il faut donc une valeur négative pour obtenir un décalage vers le haut :
<g id="decalage_1_cercle">
 <use xlink:href="#1_cercle" x="0" y="-20" />
</g>


etoile2


Maintenant que nous avons notre triangle décalé, nous pouvons le reproduire en trois exemplaires, avec une rotation d'un tiers de tour soit 120° entre chaque motif :
<g id="3_cercle">
 <use xlink:href="#decalage_1_cercle" />
 <use xlink:href="#decalage_1_cercle" transform="rotate(120)" />
 <use xlink:href="#decalage_1_cercle" transform="rotate(240)" />     
</g>


etoile3


Pour l'insérer dans les grands triangles de 10 cercles, ce groupement doit être décalé vers le haut de ( 1 + 1/3 ) hauteur de petit triangle = 30 + 10 = 40 pixels
<g id="decalage_3_cercle">
 <use xlink:href="#3_cercle" x="0" y="-40" /> 
</g>


etoile4


Comme précédemment, on répète trois fois ce motif, en tournant à chaque fois de 120° :
On n'oublie pas non plus de rajouter le cercle du centre.
<g id="10_cercle">
 <use xlink:href="#decalage_3_cercle" />
 <use xlink:href="#decalage_3_cercle" transform="rotate(120)" />
 <use xlink:href="#decalage_3_cercle" transform="rotate(240)" />     
 <use xlink:href="#1_cercle" />  
</g>

etape 5

Nous allons maintenant décaler notre figure vers le haut, pour faire chacune des 6 zones en couleur. Si l'on observe la figure, on voit que le centre des grands triangles se situe à 9 hauteurs de petits triangles par rapport au centre du jeu, soit 180 pixels. Effectuons ce décalage, pour obtenir le triangle supérieur :
<g id="decalage_casesdepart_10_cercle">
 <use xlink:href="#10_cercle" x="0" y="-180" /> 
</g>

etape 6


Nous pouvons alors obtenir les 6 camps de départ par rotation de cette figure. A chaque fois, on tourne de 1/6ème de tour, soit 60°.
<g id="casesdeparts" style="fill-opacity:0.45">
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(0)" style="stroke:yellow; fill:yellow" />
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(60)" style="stroke:orange; fill:orange" />
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(120)" style="stroke:red; fill:red" />
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(180)" style="stroke:Fuchsia; fill:Fuchsia" />
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(240)" style="stroke:blue; fill:blue" />
 <use xlink:href="#decalage_casesdepart_10_cercle" transform="rotate(300)" style="stroke:#00E0C0; fill:#00E0C0" />
</g>

On en a profité pour préciser la couleur du contour ( stroke ) et du remplissage ( fill ) de chacun des camps de base. Voici le résultat :

etape 7

Il nous reste maintenant à fabriquer l'intérieur du jeu. On calcule alors le décalage : 3 hauteurs de triangle en vertical ( 3  x 30 = 90 ), un demi-côté en horizontal ( 30 x tan 30° = 17.3 )
<g id="decalage_interieur_10_cercle">
 <use xlink:href="#10_cercle" x="17.3" y="90" /> 
</g>


etape 8

Une fois ce décalage appliqué, on fait tourner la figure 6 fois pour obtenir les 6 grands triangles du centre.
On n'oublie pas de rajouter le cercle du centre. :
<g id="interieur" style="fill:white; stroke:black">
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(0)"/>
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(60)"/>
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(120)"/>
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(180)"/>
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(240)"/>
 <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(300)"/>
 <use xlink:href="#1_cercle" />
</g>

etape 9


Il ne nous reste plus qu'à assembler les deux parties. On en profite pour indiquer une largeur de trait (stroke-width ) de 3 pixels.
<g id="game" style="stroke-width:3">
 <use xlink:href="#interieur" />
 <use xlink:href="#casesdeparts" />   
</g>


étape 10

Voilà notre jeu complet !... On peut fignoler si on le souhaite, par exemple en rajoutant un dégradé radial en arrière plan :
<radialGradient id="degrade">
 <stop style="stop-color:white" offset="0%" />
 <stop style="stop-color:grey" offset="65%" />
 <stop style="stop-color:#202020" offset="100%" />
</radialGradient>
<g id="game"
style="stroke-width:3">
 <circle r="260" style="fill:url(#
degrade); stroke:none;"/>
 <use xlink:href="#interieur" />
 <use xlink:href="#casesdeparts" />   
</g>


étape 11


Nous avons ainsi complètement défini le plateau de jeu. Les portions de code précédentes étaient dans la section "définitions", c'est à dire entre les balises <defs> et </defs>

Il ne nous reste plus quà placer le plateau ainsi défini quelque part dans le dessin. Les dimensions indiquées dans la balise svg étant width="800" height="600", on peut placer le plateau au centre de cette zone ; autrement dit avec les coordonnées x="400" y="300" :
<use xlink:href="#game" x="400" y="300" /> 

Voici le lien vers le fichier svg correspondant : etoile.svg , et ci-dessous le contenu de ce fichier :

<?xml version="1.0" encoding="iso-8859-1"?>
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
 <desc> Le jeu de l'étoile </desc>
 <title> Jeu de l'étoile </title>
 <defs>
   <circle id="1_cercle" cx="0" cy="0" r="16" />
   <g id="decalage_1_cercle">
     <use xlink:href="#1_cercle" x="0" y="-20" />
   </g>
   <g id="3_cercle">
     <use xlink:href="#decalage_1_cercle" />
     <use xlink:href="#decalage_1_cercle" transform="rotate(120)" />
     <use xlink:href="#decalage_1_cercle" transform="rotate(240)" />     
   </g>
   <g id="decalage_3_cercle">
     <use xlink:href="#3_cercle" x="0" y="-40" /> 
   </g>
   <g id="10_cercle">
     <use xlink:href="#1_cercle" />  
     <use xlink:href="#decalage_3_cercle" />
     <use xlink:href="#decalage_3_cercle" transform="rotate(120)" />
     <use xlink:href="#decalage_3_cercle" transform="rotate(240)" />     
   </g>
   <g id="decalage_home_10_cercle">
     <use xlink:href="#10_cercle" x="0" y="-180" /> 
   </g>
   <g id="casesdepart" style="fill-opacity:0.4">
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(0)" style="stroke:yellow; fill:yellow" />
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(60)" style="stroke:orange; fill:orange" />
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(120)" style="stroke:red; fill:red" />
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(180)" style="stroke:Fuchsia; fill:Fuchsia" />
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(240)" style="stroke:blue; fill:blue" />
     <use xlink:href="#decalage_home_10_cercle" transform="rotate(300)" style="stroke:#00E0C0; fill:#00E0C0" />
   </g>
   <g id="decalage_interieur_10_cercle">
     <use xlink:href="#10_cercle" x="17.3" y="90" /> 
   </g>
   <g id="interieur" style="fill:white; stroke:black">
     <use xlink:href="#1_cercle" /> 
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(0)"/>
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(60)"/>
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(120)"/>
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(180)"/>
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(240)"/>
     <use xlink:href="#decalage_interieur_10_cercle" transform="rotate(300)"/>
   </g>
   <radialGradient id="degrade">
     <stop style="stop-color:white" offset="0%" />
     <stop style="stop-color:grey" offset="65%" />
     <stop style="stop-color:#202020" offset="100%" />
   </radialGradient>
   <g id="game" style="stroke-width:3">
     <circle r="260" style="fill:url(#degrade); stroke:none;"/>
     <use xlink:href="#interieur" />
     <use xlink:href="#casesdepart" />   
   </g>
 </defs>
 <use xlink:href="#game" x="400" y="300" /> 
</svg>