Vous êtes ici : Accueil > Cours > SVG > Les filtres SVG
Les filtres SVG c'est quoi ?
Avant de présenter les filtres SVG, sachez que la compatibilité avec les navigateurs est très bonne. Vous pouvez donc les utiliser sans restriction, bien qu'il existe certains bugs selon les filtres.
Les filtres SVG permettent de changer la couleur ou l'apparence d'un élément graphique avec du code. L'avantage majeur par rapport aux filtres CSS est de pouvoir contrôler les canaux RGBA.
L'élément filter :
Il s'agit de l'élément qui va nous permettre de créer des filtres, en particulier des effets de filtre (ou primitives de filtre).
Les attributs relatifs à l'élément filter sont les suivants :
x : décalage sur l'axe des abscisses.
y : décalage sur l'axe des ordonnées.
width : largeur dans le système des coordonnées.
height : hauteur dans le système des coordonnées.
filterRes : obsolète.
filterUnits : définit le système de coordonnées pour les attributs x, y, width et height.
userSpaceOnUse.
objectBoundingBox (par défaut).
primitiveUnits : spécifie le système de coordonnées pour les valeurs de longueur dans les primitives de filtre ainsi que pour les attributs qui définissent la sous-région de primitive de filtre.
userSpaceOnUse (par défaut).
objectBoundingBox.
href : définit un lien vers une ressource en tant qu'URL de référence.
Un filtre SVG (dans son écriture la plus simple) se présente sous cette forme :
<svg>
<filter id="votreid">
...
</filter>
</svg>
💡 Dans la plupart des cas, les filtres se déclarent à l’intérieur de l'élement SVG defs dans lequel il est possible d'appliquer des styles CSS (voir plus bas).
Autant la structure d'un document SVG est simple à appréhender, autant les filtres se révèlent beaucoup plus complexes.
Exemple simple :
Ci-dessous, nous allons appliquer un simple filtre de flou avec l'élément filter sur un cercle SVG :
💡 Il existe une autre façon d'appliquer un filtre SVG sur un élément HTML : l'utilisation de CSS (avec la propriété filter). L'avantage est de pouvoir cibler plusieurs éléments avec le même filtre.
💡 Nous avons utilisé pour créer ce filtre la primitive de filtre feGaussianBlur ainsi que l'attribut stdDeviation. Nous allons voir dans ce cours les différents effets de filtres en SVG, les attributs nécessaires selon le type de filtre au travers de nombreux exemples.
Les primitives de filtre
Pour réaliser un filtre SVG, il est nécessaire de renseigner à l'intérieur dudit filtre les primitives de filtre.
Entrée et sortie des primitives de filtre :
Avant de détailler chaque primitive, il nous faut parler des entrées et sorties puisque celles-ci seront forcément utilisées dans la présentation des différents effets de filtre.
En effet, afin de créer un filtre SVG, il faut une entrée (input) et une sortie (output). L'entrée est définie via l'attribut in (vous pouvez d'ailleurs voir cet attribut dans le tout premier exemple du cours) que ce soit sur le graphique d'une forme, le canal apha d'une forme ou encore sur une sortie de filtre.
Reprenons justement le premier exemple du cours où l'on applique un filtre de flou sur une forme :
Vous pouvez voir que l'attribut in prend la valeur SourceGraphic. Pour information, voici les valeurs de cet attribut d'entrée de filtre :
SourceGraphic : représente le graphique d'origine qui fait référence au filtre
SourceAlpha : représente le canal alpha uniquement du graphique d'origine qui fait référence au filtre
BackgroundImage : représente un instantané d'image du canevas sous la région de filtre au moment où l'élément de filtre a été appelé
BackgroundAlpha : représente le canal alpha d'un instantané d'image du canevas sous la région de filtre au moment où l'élément de filtre a été appelé
FillPaint : représente la valeur de la propriété fill sur l'élément cible pour l'effet de filtre et est conceptuellement infinie
StrokePaint : représente la valeur de la propriété stroke sur l'élément cible pour l'effet de filtre et est également conceptuellement infini
Une référence de primitive de filtre : nom donné à la sortie d'une primitive de filtre précédente dans le même filtre. Vous pouvez mettre le terme que vous souhaitez.
Concernant la sortie, on utilisera l'attribut result (autrement dit le résultat de l'opération) et prend comme valeur un nom que vous choisissez.
💡 A retenir : une entrée est définie via l'attribut in, tandis que la sortie est définie par l'attribut result. Par ailleurs, sachez qu'une sortie de filtre peut être utilisée comme entrée de filtre comme dans l'exemple ci-dessous :
Le filtre de couleur de matrice donne la possibilité de manipuler la couleur (si vous utilisez Photoshop, cela pourrait vous aider à comprendre cet effet de filtre) en recalculant la valeur de chaque pixel de l’image.
La primitive de filtre feColorMatrix possède deux attributs : type et values.
L'attribut type peut prendre les effets prédéfinis suivants :
💡 Les valeurs de l'attribut values sont comprises entre 0 et 360°. Il s’agit d’une rotation sur le cercle chromatique. Attention une rotation de 360° équivaut à une rotation de 0°.
💡 La saturation permet d’abaisser ou augmenter l’intensité des couleurs d’une image.Si la valeur est 0 alors l'image est en nuances de gris et si la valeur est 1 alors l'image filtrée est identique à l'original. Si la valeur est supérieure à 1 il y a saturation.
La primitive feComponentTransfer permet de manipuler chacun des quatre canaux de couleur (RGBA) séparément. Il permet aux opérations d'ajuster la luminosité, le contraste ou l'intensité (balance des couleurs) des couleurs. Il permet également le seuillage ou la segmentation d'image.
Par ailleurs, la primitive de filtre feComponentTransfer comprend les fonctions de transfert suivantes :
Fonction feFuncR = rouge
Fonction feFuncG = vert
Fonction feFuncB = bleu
Fonction feFuncA = alpha
💡 Vous pouvez inclure un ou plusieurs de ces canaux. Si toutefois, vous utilisez la même fonction plus d'une fois, la dernière des deux sera prise en compte.
Enfin, il existe cinq types possibles pour chacune des fonctions :
💡 Le type table fonctionne avec l'attribut tableValues auquel on ajoute des valeurs comprises entre 0 et 1. Dans l'exemple ci-dessus, on a modifié les valeurs du canal bleu via la fonction de transfert feFuncB.
La primitive feComposite permet de combiner deux images d'entrée de différentes manières. Les deux entrées sont spécifiées en utilisant les attributs in et in2. Toutes deux peuvent accepter l'une des valeurs de mot-clé pour l'entrée d'un bien comme le résultat d'une autre primitive de filtre à l'intérieur du même filtre.
La primitive feComposite fonctionne avec l'attribut operator qui possède six valeurs :
over
in
out
atop
xor
arithmetic : comprend les attributs k1, k2, k3 et k4
duplicate (si l'attribut n'est pas spécifié, il prend cette valeur)
wrap
none
kernelUnitLength : détermine la distance prévue.
preserveAlpha : indique comment l'effet traite la transparence alpha. Par défaut, cet attribut prend la valeur false, ce qui signifie que l'effet couvre tous les canaux (RGBA). Si la valeur est true, alors l'attribut ne gère pas la transparence.
La primitive feDiffuseLighting est utilisée pour montrer la tridimensionnalité d'un objet, pour éclaircir un objet, ou pour éclairer une partie spécifique d'un objet ou d'un arrière-plan.
Cette primitive comprend quatre attributs :
in : détermine le type d'entrée.
surfaceScale : détermine la hauteur de la surface pour une valeur alpha de 1 (par défaut).
diffuseConstant : détermine la valeur RVB finale d'un pixel donné (valeur négative non acceptée).
kernelUnitLength : Indique la distance prévue
La couleur de lumière est spécifiée par la propriété lighting-color.
Outre les attributs in (c'est l'image qui est déplacée) et in2 (c'est l'image qui va servir à déplacer l'image définie dans le précédent attribut), ce primitive de filtre comprend les attributs suivants :
scale : détermine la distance nécessaire pour déplacer les pixels de l'image via l'attribut in. 0 est la valeur par défaut.
xChannelSelector : détermine le type de canal utilisé via l'attribut in2 pour déplacer les pixels de l'image contenue dans l'attribut in le long de l'axe des x. La valeur par défaut est A ou le canal alpha.
yChannelSelector : même fonction que l'attribut xChannelSelector mais concerne le long de l'axe y. La valeur par défaut est A ou le canal alpha.
En photographie, l'effet se nomme Bokeh. Il s'agit d'un effet similaire à la primitive de filtre de flou gaussien (ce terme doit parler aux utilisateurs de Photoshop) qui agit sur chaque pixel présent dans la partie que l'on souhaite flouter.
Ce filtre comprend l'attribut stdDeviation dont la valeur est un nombre supérieur à zéro. On peut renseigner deux nombres, séparés par une virgule, pour contrôler les axes x et y.
Un autre exemple tiré de cette démonstration mais en pur SVG :
Le code ci-dessous. Vous pouvez remarquer qu'on utilise la même image deux fois. En appliquant un masque avec un dégradé sur la seconde image, on laisse ainsi passer la lumière et par conséquent on peut voir une partie de la première image, la même que l'on a masquée dans la seconde. Ainsi, le filtre de flou ressort-il sur les angles de l'image.
Cette primitive de filtre récupère les données d'une image provenant d'une source externe (via l'attribut href) et rend en sortie les données en pixels quel que soit le type d'image. Elle est similaire à l'élément image et comprend les mêmes attributs.
La primitive de filtre feMerge permet d'empiler les résultats de différents filtres. Généralement, elle est utilisée comme dernière primitive d’un filtre pour assembler les différents résultats précédents (voir chapitre Combiner plusieurs primitives de filtre).
L'effet de filtre feMorphology permet de modifier la morphologie (comme son nom peut l'indiquer) de l’image d’entrée du filtre. Il existe deux types de transformation : la dilatation et la contraction.
On utilisera alors l’attribut operator qui comprend la valeur erode pour la contraction (ou érosion) et dilate pour la dilatation.
Il est possible de contrôler le niveau de contraction ou de dilatation via l’attribut radius dont la valeur est un nombre positif. On peut renseigner deux nombres, séparés par une virgule, pour contrôler les axes x et y.
La primitive feOffset décale tout simplement l’image d’entrée selon les attributs dx et dy. Cette primitive s'avère utile pour créer des effets d’ombrage, que nous verrons plus loin dans le chapitre Combiner plusieurs primitives de filtre.
surfaceScale : détermine la hauteur de la surface pour une valeur alpha de 1 (par défaut).
specularConstant : représente la valeur de ks (coefficient de réflexion spéculaire de la matière) selon le modèle d'éclairage de Phong. La valeur par défaut est de 1.
specularExponent : contrôle la mise au point pour la source de lumière. Plus la valeur est grande, plus la lumière est intense. La valeur doit être comprise entre 1,0 à 128,0.
La primitive feTurbulence va permettre de créer des motifs ou des textures. Elle comprend les attributs suivants :
baseFrequency : détermine la vitesse de variations des couleurs sous la forme d'un décimal compris entre .01 et .1. Par défaut, il s'agit de zéro. Peut prendre deux nombres séparés par une virgule correspondant aux axes x et y.
numOctaves : permet de régler la finesse. La valeur par défaut est 1.
seed : valeur d’initialisation du générateur de nombre aléatoire. (par défaut = 0)
stitchTiles
stitch
noStitch (par défaut)
type
turbulence
fractalNoise
On notera l'absence de l'attribut in. Il n'y a donc pas d'entrée pour cet effet de filtre.
Cette primitive définit une source de lumière distante pouvant être utilisée dans une primitive de filtre d'éclairage telles que feDiffuseLighting ou feSpecularLighting .
Il existe deux attributs pour cet effet de filtre :
azimuth : représente l'angle de direction de la source de lumière sur le plan XY (dans le sens des aiguilles d'une montre), en degrés par rapport à l'axe x. (Par défaut = 0).
elevation : représente l'angle de direction de la source de lumière du plan XY vers l'axe z, en degrés. Notez que l'axe Z pointe vers l'observateur du contenu. (Par défaut = 0).
La primitive de filtre fePointLight permet de créer un effet de lumière ponctuelle et comprend trois attributs : x, y et z dont la valeur pour chacun est un nombre.
La primitive de filtre feSpotLight permet de créer un effet de projecteur. Elle fonctionne également avec les mêmes primitives que fePointLight. Elle comprend aussi les mêmes attributs mais en possède d'autres :
pointsAtX : représente l'emplacement X dans le système de coordonnées établi par l'attribut primitiveUnits sur l'élément filter à partir du point sur lequel la source lumineuse pointe. (Par défaut = 0)
pointsAtY : représente l'emplacement Y dans le système de coordonnées établi par l'attribut primitiveUnits sur l'élément filter à partir du point sur lequel la source lumineuse pointe. (Par défaut = 0)
pointsAtZ : représente l'emplacement X dans le système de coordonnées établi par l'attribut primitiveUnits sur l'élément filter à partir du point sur lequel la source lumineuse pointe. De plus, l'axe Z positif doit pointer dans le contenu visible. (Par défaut = 0)
specularExponent : contrôle la mise au point pour la source de lumière.
limitingConeAngle : représente l'angle en degrés entre l'axe de la lumière spot et le cône de lumière spot. Ainsi aucune lumière ne peut-elle sortir du cône.
Nous avons fait le tour des primitives de filtre. C'est assez indigeste, il faut bien le reconnaître. Et pourtant j'ai laissé volontairement des informations de côté.
Combiner les résultats de plusieurs primitives de filtre
Si vous avez lu avec assiduité (je n'en doute pas une seconde) le chapitre sur les primitives de filtre, vous savez donc que la primitive feMerge va nous permettre d'empiler les résultats de différents filtres, autrement dit de combiner plusieurs effets de filtre.
Pour être plus précis, sachant que les filtres SVG produisent des couches intermédiaires avant de créer une image finale en sortie, la primitive feMerge va se charger de placer cesdites couches les unes sur les autres pour finalement réduire toutes les couches en un seul résultat.
Voyons un exemple que nous avons déjà utilisé plus haut, à savoir une ombre portée. Pour ce faire, nous allons nous servir de la primitive de filtre feGaussianBlur en corrélation avec d'autres primitives telles que feOffset, feFlood, feComposite et bien entendu feMerge :
Vous noterez la présence de la primitive enfant de feMerge, à savoir feMergeNode. L'ordre de cette primitive a son importance puisque la couche qui sera déclarée en dernier se trouvera en dessus de toutes les autres.
Autre exemple où nous allons utiliser d'autres primitives et les combiner afin d'obtenir un résultat (ici, une ombre incrustée) :