Jusqu’à maintenant, nous n’avons pu remplir nos formes qu’avec une couleur unie. Cela va changer : les deux prochains chapitres traitent en profondeur des motifs (ou textures) et des dégradés.
L’élément pattern sert à définir un motif. Il n’est jamais affiché directement mais nous le placerons tout de même dans defs car c’est à cet endroit que viennent se placer les éléments réutilisables.
Si on veut pouvoir utiliser un pattern, il faut pouvoir l’identifier grâce à un identifiant. Il portera donc toujours un attribut id.
On peut utiliser un motif pour remplir un objet, c’est à dire avec la propriété CSS fill, mais aussi pour remplir la bordure d’un objet, avec stroke. Au lieu d’un nom de couleur, on écrira : url(fichier.svg#identifiant) où l’identifiant désigne un pattern dans le fichier adéquat (qui n’est pas forcément le même que celui ou l’on dessine, on peut donc facilement réutiliser ses pattern). Par exemple :
Tout d’abord, il faut définir la taille de notre motif ainis que son point de départ. Il sera par la suite répété indéfiniment dans toutes les directions pour former une mosaïque. On définit le point de départ grâce aux attributs x et y. Puis on défini la taille du motif grâce aux attributs width et height. Ça, vous connaissez déjà. Enfin, vous mettez entre la balise de début et la balise de fin de pattern les formes qui composeront votre motif, par exemple un circle, ou un path, etc. Vous pouvez les styler à votre guise avec CSS et les animer autant que vous voulez !
Mais au fait, les attributs x, y, width et height, à quoi font-t-ils référence ? C’est là que débutent les problèmes : cela dépend de la valeur de l’attribut patterUnits.
Lorsque l’attribut patterUnits de pattern est positionné à la valeur userSpaceOnUse, les quatre attributs listé ci-dessus font référence au système de coordonné courrant, c’est à dire dans la plupart des cas à l’élément svg le plus proche. SVG va donc commencer à dessiner notre motif, qui est un rectangle, à partir du point de coordonnées donné par les attributs x et y. Il va ensuite répéter le motif pour créer une mosaïque. Les coordonnées n’ont donc aucun rapport avec la forme sur laquelle on applique la texture !
Pour ce shcéma, on a pris x="10", y="0", width="40" et height="20" :
Remarquez comme le premier motif est décalé de 10 pixels par rapport au point 0,0
Lorsque patterUnits est fixé à objectBoundingBox, le processeur SVG commence par déterminer la boîte englobante de la forme sur laquelle on applique la texture, c’est à dire le plus petit rectangle contenant cet objet. Ensuite, on ne résonne plus en fonction du système de coordonné courrant mais en fonction de cette boîte englobante. Les attributs x, y, width et height font à présent référence aux dimensions de la boîte englobante. Dans ce cas, les attributs width et height sont exprimés en pourcentage de la boîte englobante. Dans l’exemple suivant, on a à chaque fois un motif qui se répète cinq fois horizontalement (à cause du width="20%") et quatre fois verticalement (height="25%").
Notez bien qu’objectBoundingBox est la valeur par défaut !
Par défaut, les unités des objets qui constituent un pattern sont exprimées dans le système de coordonnées de l’élément svg parent. Dans ce cas, l’attribut patternContentUnits vaut userSpaceOnUse. Cependant, on peut vouloir que les unités soient précisées en fonction de la boîte englobante de l’objet sur lequel on applique la texture. Dans ce cas, on fixe patternContentUnits à objectBoundingBox et on spécifie les valeurs en pourcentages. C’est très utile quand on veut qu’un motif se répète en entier un nombre de fois précis, horizontalement et verticalement, et quelque soit le motif sur lequel on l’applique :
Si vous avez des objets qui se remplissent uniformément d’une seule couleur, c’est sans doute que la valeur de votre stroke-width est trop grande : elle est aussi exprimée en pourcentage de la boîte englobante !
SVG permet d’appliquer des transformations sur des motifs. On se sert alors de l’attribut patternTransform qui prend en paramêtre une liste de transformations. Effectuons un skewX puis un skewY sur un rectangle en motif :
Vous n’êtes bien sur pas limité à une seule transformation.
Notez que la transformation est effectuée sur la texture en entier, et non pas sur le contenu du pattern.
L’inclusion de motifs dans des motifs se fait de façon très intuitives. En fait, on utilise toujours les mêmes propriétés CSS (à savoir fill et stroke, pour effectuer le texturage. Voici un exemple plutôt sympathique et qui serait quasiment impossible à obtenir sans l’inclusion de motif dans un motif :
Et voilà le travail ! Et vous pourrez faire bien mieux, j’en suis sur !
Ce chapitre touche à sa fin, mais en fait, le prochain traite de quelquechose d’assez proche, qui permet aussi le remplissage : les dégradés. Prenez une pause de cinq minutes, soufflez un peu et on repart !