L'effet gluant avec SVG

Lucas Bebber, développeur brésilien hyper créatif, propose son effet Gooey, qui a fait le buzz dernièrement. Outre une dose d'inspiration, on y trouvera de bonnes bases sur les filtres SVG.

Par

L’article qui suit est de Lucas Bebber. Il est le créateur de quelques-uns des effets les plus créatifs que j’aie jamais vus sur le web. À tel point que je n’ai pas pu m’empêcher de blogguer plusieurs fois à leur sujet. Mais cette fois, nous avons mieux : Lucas lui-même, qui nous explique comment fonctionnent les filtres SVG et comment les utiliser pour créer un effet gluant très cool (Chris Coyier).

Il y a quelque temps, Chris a écrit un article sur Shape Bobbling en CSS. L’effet est cool et la technique est intelligente, mais l’approche via les filtres CSS habituels comporte certains inconvénients : pas de transparence, pas de contenu à l’intérieur des gouttes (les blobs), utilisation d’autres couleurs que le noir et blanc difficile, etc.

Mais dernièrement, en m’amusant avec les filtres SVG, je me suis dit que je pourrais les utiliser pour résoudre la plupart des problèmes créés par l’approche CSS pure. Voici un menu gooey (gluant, visqueux) que j’ai réalisé pour démontrer l’effet, cliquez sur le menu pour le voir en action :

See the Pen CSS Gooey Menu (Version 1) by Lucas Bebber (@lbebber) on CodePen.

Les filtres SVG

Les filtres SVG sont très puissants. Il y aurait beaucoup de choses à dire à leur sujet, mais nous allons nous limiter aux bases nécessaires pour comprendre comment l’effet fonctionne.

Comme leur nom ne l’indique pas, nous pouvons appliquer les filtres SVG sur des éléments habituels du DOM via CSS, dans la plupart des navigateurs.

Voici la syntaxe basique pour définir un filtre :

//SVG
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <filter id="nom-de-votre-filtre-ici">
      ...          
      <!-- insérez les filtres ici -->
      ...
    </filter>
    ...
  </defs>
</svg>

Pour appliquer un filtre SVG à un élément du DOM :

//CSS
.selector {
  filter: url(’#nom-de-votre-filtre-ici’);

  /* vous pouvez aussi charger les filtres depuis des SVG externes de cette façon: */
  filter: url(’filters.svg#nom-de-votre-autre-filtre-ici’);
}

Vous aurez peut-être besoin de préfixes constructeurs (vendor prefixes) pour utiliser la propriété filter.

Un élément <filter> contient une ou plusieurs primitives, qui sont des des opérations réalisées par le filtre, p.ex. le flou, la transformation de couleur, l’ombrage, etc. Vous pouvez trouver une liste complète des primitives de filtres ici.

Regardons quelques exemples.

See the Pen svg blur demonstration by Lucas Bebber (@lbebber) on CodePen.

//SVG
<filter id="blur">
  <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>

Ce filtre applique un flou de 3px sur l’objet. Remarquez l’attribut in="SourceGraphic". L’attribut in définit l’input d’une primitive de filtre. SourceGraphic est un mot-clé qui retourne le graphique original de l’élément, avant le filtre. En d’autres termes, l’input du filtre floutage (blur) sera le graphique original de l’objet. C’est simple.

Maintenant, voyons un effet habituel mais assez complexe : une ombre portée. Cela nous servira pour montrer comment on peut enchaîner les primitives de filtres :

See the Pen svg drop shadow demonstration by Lucas Bebber (@lbebber) on CodePen.

//SVG
<filter id="drop-shadow">
  <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="shadow" />
  <feOffset in="shadow" dx="3" dy="4" result="shadow" />
  <feColorMatrix in="shadow" mode="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.6 0" result="shadow" />
  <feBlend in="SourceGraphic" in2="shadow" />
</filter>

Regardez l’attribut result du premier filtre et les attributs in suivants. Avec l’attribut result on peut nommer le résultat d’un filtre et appliquer un filtre à ce résultat plutôt qu’au graphique source. Cela vous permet, dans cet exemple, de flouter un objet, d’assombrir l’objet flouté, et de déplacer la position de l’objet flou et sombre.

Faites bien attention au dernier élément ici, la primitive <feBlend>. Elle est là pour montrer comment certaines primitives de filtres peuvent accepter des inputs multiples (le paramètre in2) et que vous pouvez appeler le mot-clé sourceGraphic plusieurs fois à n’importe quel endroit du filtre. Dans cet exemple, le dernier filtre accepte à la fois le mot-clé sourceGraphic et le résultat shadow pour remettre l’image originale au-dessus de l’ombre que nous venons de créer.

Maintenant que nous avons vu les bases des filtres SVG, voyons comment nous pouvons céer cet effet gooey.

Faire tenir les choses ensemble

La technique de base a été décrite ici. Pour récapituler, l’idée est de flouter ensemble deux objets ou plus, et d’augmenter le contraste. C’est simple et ça marche :

See the Pen metaballs demonstration by Lucas Bebber (@lbebber) on CodePen.

Toutefois, comme nous l’avons déjà dit, cela comporte les inconvénients suivants :

  1. ça crée un désordre dans les couleurs, il est difficile de faire autre chose que du noir et blanc
  2. tout le contenu est flouté, ce qui le rend inutilisable
  3. le container doit avoir un background, donc il n’y a pas de transparence possible.

Tout cela contribue à rendre l’effet difficilement utilisable en pratique.

Avec les filtres SVG cependant, nous pouvons réaliser des choses impossibles à faire avec les seuls filtres CSS. Nous pouvons augmenter le contraste du seul canal alpha, et ne pas changer les couleurs. Nous pouvons, grâce au mot-clé sourceGraphic que nous venons de voir, rendre le contenu visible. Puisque nous travaillons avec le canal alpha, non seulement il sera transparent, mais un background transparent sera également requis, ne l’oubliez pas.

Voici le code de base :

//SVG
<filter id="goo">
  <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
  <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7" result="goo" />
  <feBlend in="SourceGraphic" in2="goo" />
</filter>

Il est très court, voici comment il se décompose :

  1. D’abord, nous appliquons un flou de 10px sur le sourceGraphic et nous nommons ce résultat.
  2. Ensuite, nous appliquons au résultat précédent un filtre de matrice couleur afin d’augmenter le contraste du cana alpha.
  3. Enfin, nous insérons le graphique original au-dessus de l’effet que nous venons de créer.

Sur les matrices de couleurs

Si vous n’avez jamais utilisé de filtre matrice couleur, voici quelques explications. Vous pouvez le voir comme un tableau comportant quatre rangées et 5 colonnes, comme ceci :

   | R | G | B | A | +
---|-------------------
 R | 1 | 0 | 0 | 0 | 0
---|-------------------
 G | 0 | 1 | 0 | 0 | 0
---|-------------------
 B | 0 | 0 | 1 | 0 | 0
---|-------------------
 A | 0 | 0 | 0 | 1 | 0
---|-------------------

Chaque rangée représente un canal (rouge, vert, bleu, alpha) et est utilisé pour fixer la valeur du canal. Chacune des quatre premières colonnes représente également un canal, et elles retournent la valeur présente de leur canaux respectifs. Il y a un nombre dans chaque cellule. Celui-ci ajoute au canal de sa rangée le résultat de la multiplication de ce nombre par la valeur présente du canal de sa colonne. Par exemple, si on a 0.5 à l’intersection de la rangée R (rouge) et de la colonne G (vert), cela aura pour effet d’ajouter (pour chaque pixel) au canal rouge la valeur présente de vert multipliée par 0.5. La dernière colonne ne représente aucun canal, elle est utilisée pour l’addition ou la soustraction, ce qui signifie qu’on ajoutera/retranchera au canal concerné un nombre de cette colonne multiplié par 255.

Voilà une explication bien longue et peut-être pas encore très claire, mais en fait l’utilisation du filtre est très simple. Dans notre exemple, puisque nous n’augmentons que le contraste du canal alpha, notre matrice ressemblera à ceci :

   | R | G | B | A | +
---|-------------------
 R | 1 | 0 | 0 | 0 | 0
---|-------------------
 G | 0 | 1 | 0 | 0 | 0
---|-------------------
 B | 0 | 0 | 1 | 0 | 0
---|-------------------
 A | 0 | 0 | 0 |18 |-7
---|-------------------

Les canaux RGB sont inchangés. La valeur du canal alpha est multipliée par 18 et on soustrait à cette valeur 7 * 255, ce qui augmente effectivement le contraste de la transparence seule. Ces valeurs peuvent être adaptées selon vos besoins.

Pour appliquer cette matrice à notre filtre feColorMatrix, tout ce que nous avons à faire est d’écrire ces suites de nombres de manière séquentielle, comme ceci :

values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7"

Démo

Et voilà, notre effet de base est prêt ! Le voici :

See the Pen svg goo effect demonstration by Lucas Bebber (@lbebber) on CodePen.

Vous pouvez le personnaliser selon vos besoins, par exemple en y ajoutant une ombre portée, en utilisant des couleurs différentes pour chaque élément, ou tout ce que vous voulez !

Dernières considérations

  • Le filtre doit être appliqué au container des éléments, et non aux éléments eux-mêmes.
  • Le container ne doit pas avoir de bavures sur les côtés, autrement dit il doit être un peu plus grand que son contenu, sinon vous risquez d’avoir ce genre de problèmes sur les bords :


bavures
Quelques bavures sur les côtés

  • Pour pouvoir appliquer ce filtre à des objets pointus tels que des rectangles, il existe une approche un peu plus sophistiquée. Au lieu de simplement dessiner l’image au-dessus de l’effet gooey, nous utilisons le filtre feComposite avec l’opérateur atop pour masquer tout ce qui est extérieur à notre matière visqueuse (au goo !).

Ainsi :

//SVG
<filter id="fancy-goo">
      <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
      <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
      <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>

See the Pen comparison between methods of applying the goo filter by Lucas Bebber (@lbebber) on CodePen.

De cette façon, nous pouvons utiliser le filtre non seulement pour cet effet gooey élaboré, mais aussi pour des applications beaucoup plus simples comme, par exemple, d’arrondir les angles de formes constituées de rectangles multiples.

  • Ce filtre, bien que de taille réduite, peut être gourmand en ressources si on l’applique sur des étendues larges, soyez attentifs.

Compatibilité

Les filtres SVG ont une bonne compatibilité, mais tous les navigateurs ne supportent pas leur application à des éléments habituels du DOM, en particulier Safari. Cependant, ils fonctionnent sur Firefox et Chrome, même en version Android, et le filtre se dégrade correctement s’il ne fonctionne pas. Si vous avez absolument besoin de faire fonctionner cet effet dans tous les navigateurs, envisagez l’utilisation d’éléments SVG au lieu d’éléments du DOM.


Intéressé par SVG et CSS ? Sur la Cascade, retrouvez :

des articles et ressources sur SVG
des articles et ressources sur CSS


Ressources complémentaires en français

Guide des animations SMIL, par Sara Soueidan
SVG, style et animation avec CSS, par Sara Soueidan
Animer un SVG avec CSS, par Chris Coyier
Utiliser SVG, par Chris Coyier
Le morphing en SVG, par Chris Coyier

Liste des articles sur SVG dans la Cascade


original paru le dans CSS-Tricks.

Sur l’auteur : est un designer brésilien, il travaille pour l’agence Garden Studio (jetez un coup d’oeil au site de l’agence, ça vaut le coup !!). Vous pouvez le retrouver sur Twitter, Dribbble, Flickr et CodePen.

NdT : CSS-Tricks est un site ressource d’une richesse exceptionnelle, axé sur CSS et le web design en général. Vous pouvez suivre son actualité sur Twitter, Facebook, YouTube, GitHub. Mélange d’articles, de vidéos, de forums, de ressources diverses (jetez un coup d’oeil à son "Almanac" ), il est très populaire sur le web anglophone.

CodePen est un site où vous pouvez tester votre code, faire des maquettes, proposer vos dernières créations et recueillir les observations de vos pairs. C’est aussi une source d’inspiration pour vos propres designs.

Traduit avec l’aimable permission de CSS-Tricks et de l’auteur.
Copyright CSS-Tricks © 2015.