SVGround : cours SVG

viewBox, conservation du ratio, symboles et autres gourmandises

La zone de dessin

Tout d’abord, sachez que depuis le début de ce cours, je vous trompe. Les plus curieux d’entre vous l’auront sans doute remarqué en regardant le code source des exemples : ce n’est pas le même code source que ce que j’ai recopié sur ces pages. En effet, vous avez dû remarquer que les exemples affichés en SVG tiennent miraculeusement bien dans les cadres prévus à cet effet. Ni trop grands, ni trop petits, ils tiennent pile-poil dans l’espace prévu ! Cette fonctionnalité que j’ai préféré vous cacher car elle est un peu compliquée à comprendre est vraiment très très utile. La preuve : je vous bluffe depuis le début B-).

À vrai dire le coup de bluff n’est pas très difficile puisqu’une seule ligne de code SVG change, et c’est la première :

]]>

devient

]]>

ce qui est légèrement différent !

Avant de vous expliquer tout ça, reprenons dès le début. Lorsqu’on faisait

]]>

on pense demander un document SVG de largeur 400 pixels (le pixel est l’unité par défaut) et de 300 pixels de hauteur. Et on a tout à fait raison ! Mais comme par hasard, la zone dans laquelle nous dessinons (quand on fait ) mesure 400 sur 300… Étrange :|.

En fait, point de complot. D’ailleurs, ce comportement est celui auquel on s’attend. Mais SVG permet quelque chose de bien plus puissant et flexible : on peut demander à ce que la taille réelle du dessin SVG soit différente des coordonnées de la zone de dessin. La taille réelle du dessin SVG sera exprimée grâce aux attributs width et height que vous connaissez déjà, alors que la zone de dessin sera déterminée par la valeur de l’attribut viewBox. Ensuite, absolument toutes les coordonnées données dans la suite du document seront fixées dans les coordonnées de la zone de dessin, donc par la fameuse viewBox. Les valeurs de width et de height n’ont plus aucune importance. L’attribut viewBox doit préciser quatre valeur (sans unités) : le point x minimum, le point y minimum, la largeur et la hauteur.

À quoi ça sert ? Et bien dans beaucoup de cas, ça simplifie grandement les choses. Imaginez que vous voulez coder une carte de votre ville en SVG. Le choix le plus judicieux pour n’importe système de cartographie est d’utiliser les coordonnées GPS. Mais imaginez que vous voulez en même temps avoir une taille fixe pour votre plan : 400 pixels sur 300. Il suffit d’utiliser ces mesures pour la taille réelle du dessin SVG (les attributs width et height) et de spécifier une viewBox dans le système de coordonnées du GPS :

]]>

Second exemple : imaginez que vous écrivez un cours sur SVG (tiens tiens ^^') et qu’une des caractéristique du site sur lequel vous le publiez est d’avoir un design extensible, c’est à dire qui s’adapte à la taille de l’écran. Dans ce cas, les exemples en SVG doivent aussi s’adapter à la taille de leur conteneur (un object spécifié en pourcentage). Dans ce cas, le coup de génie est d’utiliser tout simplement une largeur et une hauteur de 100%, et de spécifier une viewBox adaptée à nos besoin. Dans l’exemple suivant, le point d’origine (0, 0) ne se trouve plus, comme d’habitude, en haut à gauche mais au milieu :

<]]> < Une viewBox centrée en zéro ]]>
Une viewBox centrée en zéro

Remarquer que le ratio est ici de 4/3 pour la taille réelle du dessin (400px/300px) et également de 4/3 pour la zone de dessin en coordonnées utilisateur (40/30 de la viewBox). Mais que se passe-t-il si ce ratio ne coïncide pas ?

Contrôle du ratio

La réponse est qu’on décide entre trois scénarii :

L’attribut permettant de contrôler ce comportement est preserveAspectRatio.

preserveAspectRatio à none

Rien de plus simple quand preserveAspectRatio est fixé à la valeur none : le dessin est étiré de manière à remplir tout l’espace disponible. Voici un exemple :

<]]> < preserveAspectRatio fixé à la valeur none ]]>
preserveAspectRatio fixé à la valeur none

Dans cet exemple, on a viewBox="0 0 100 100" et donc la zone de dessin en coordonnées utilisateurs est un carré. On y dessine un cercle en plein milieu. Lors de l’affichage, le dessin réel prend toute la place disponible en hauteur et en largeur, qui n’a presque aucune chance d’être un carré (ou alors votre écran est sacrément bizarre !). Le graphique est alors étiré pour occuper l’espace, et le cercle affiché n’a rien d’un cercle : le ratio n’est pas conservé.

Heureusement il est possible de conserver le ratio, et ce grâce aux spécificateurs meet et slice.

preserveAspectRatio à meet

Avec le spécificateur meet, le dessin contenu dans la zone de dessin en coordonnées utilisateur (viewBox) sera totalement visible. Il est étiré ou rétréci pour tenir dans le dessin SVG en taille réelle, et il a sa taille maximale. Mais il reste une question. Si les ratios ne sont pas les mêmes, il y a forcément rétrécissement ou étirement. Dans ce cas, ou est placé le dessin en coordonnées utilisateur ?

Il faut concaténer deux mots clefs entre :

Ainsi en reprenant l’exemple précédent mais en remplaçant la valeur de preserveAspectRatio par xMaxYMid meet on obtient :

preserveAspectRatio fixé à la valeur meet

Si le dessin se retrouve à droite, c’est à cause de xMax. Si on avait mis xMid, le dessin aurait été centré et avec xMin, à gauche. Par contre, la valeur YMid ne sert à rien ici puisque le dessin SVG est plus large que haut. Mais si ce n’est pas le cas, regardez ce qui se passe (il s’agit de même dessin) :

preserveAspectRatio fixé à la valeur meet

Là c’est le YMid qui est utilisé, et le dessin est centré verticalement.

preserveAspectRatio à slice

Inversez le tout, dites que c’est le zone de dessin à taille réelle qui doit tenir dans la zone de dessin en coordonnées utilisateurs et vous obtenez le spécificateur slice. Quoi, ce n’est pas clair ? %)

En fait, avec slice, le dessin est étiré, sort de la zone de dessin en taille réelle mais en largeur uniquement, ou en hauteur uniquement. Bref, d’une mais pas des deux. On perd donc une partie du dessin, d’ou le nom du spécificateur (slice signifie tranche). Reprenons les exemples précédents en remplaçant meet par slice :

preserveAspectRatio fixé à la valeur slice

Retournement de situation, ici c’est YMid qui est déterminant. Que se passe-t-il lorsque la hauteur est supérieure à la largeur ? Si vous le devinez sans regarder l’exemple, c’est que vous avez tout compris à la conservation du ratio !

preserveAspectRatio fixé à la valeur slice

C’est donc bien xMax qui détermine la position du cercle. Rien ne vaut un exemple récapitulatif pour toutes les valeurs possibles (celui-ci fait partie de la suite de test de SVG du W3C) :

Exemple récapitulatif

Pour ouvrir le document seul dans votre navigateur, clic droit puis « Ce cadre » -> « Afficher ce cadre uniquement » sous Firefox, « Open image » ou « Ouvrir l’image » sous Opera.

Symboles

Les symboles sont destiné à représenter un modèle qui sera réutilisé souvent dans le document, ou dans d’autres documents, et est voué à être utilisé avec use puisqu’ils ne sont jamais affichés tel quel. La balise correspondante est symbol et peut contenir une description (avec desc). D’ailleurs, c’est mieux !

En plus de tout cela, on utilise les deux attributs viewBox et preserveAspectRatio respectivement pour fixer la taille de la zone de dessin et le comportement lors de l’utilisation avec use. En effet, lorsqu’on l’appelle avec cet élément, on doit renseigner les attributs width et height. Et dans le cas ou le ratio de ces deux attributs n’est pas le même que celui de la viewBox du symbole, c’est preserveAspectRatio qui détermine le comportement à adopter.

Dessinons grossièrement le symbole d’un avion et utilisons le (les symboles sont très utiles en cartographie) :

<]]> < Utilisation d’un symbole Aéroport ]]>
Utilisation d’un symbole

Bien sûr, ce dessin est hideux mais rien ne vous empêche de vous écrire une petite bibliothèque de sigles et de les réutiliser ensuite dans vos documents !

Les vues SVG

Les vues SVG permettent de modifier le rendu d’un fichier SVG via son URI. Il est notamment possible de redéfinir la viewBox, le contrôle du ratio ainsi que d’effectuer des transformation.

Dans la pratique, on ajoute #svgView() à la fin du nom de fichier SVG. Il vient entre parenthèses les différentes opérations à effectuer, dont ces trois que nous allons étudier (car ce sont les plus intéressantes) :

N’oubliez pas que les espaces ne sont pas autorisés dans les URI, donc utilisez les virgules pour séparer les valeurs numériques.

Prenons un document SVG de référence :

<]]> < Document de référence pour expérimentations de vues SVG Coucou ! ]]>
Document de référence pour expérimentations de vues SVG

Comme vous pouvez le constater, il y a un texte illisible car trop petit en haut à gauche. Changeons la viewBox grâce à une vue SVG pour pouvoir le lire. L’URL devient images/cours/viewbox/reference.svg#svgView(viewBox(8,25,40,30)).

Changement de viewBox avec une vue SVG

Il devient tout aussi simple de renverser le dessin, grâce à une simple rotation. L’URL est images/cours/viewbox/reference.svg#svgView(transform(rotate(180,200,150)))

Retournement d’un dessin SVG grâce à une vue SVG

Enfin on peut enchaîner les différentes possibilités. Prenons cette URI :

Plusieurs options pour une vue

Ce chapitre touche à sa fin mais n’hésitez pas à le relire car c’est assez complexe. Et il serait dommage de passer à côté : c’est vraiment très utile. Dans le prochain chapitre, il est question d’animation et croyez moi, vous aller découvrir des trucs vraiment kewl B-).

Les filtres
Aller plus loin avec les animations