Article écrit par Victor Darras
Bonjour à tous aujourd’hui je voudrais prendre un peu de temps pour vous expliquer une méthode bien pratique pour animer des SVG notamment pour faire du morphing et rendre toujours plus renversantes vos landing pages.
TropLongPasLu : Faisons ensemble l’animation suivante !
See the Pen Card Icons Animation by Victor Darras (@victordarras) on CodePen.
Revenons dans un premier temps sur le SVG si vous le voulez bien. Format vectoriel par excellence il est aussi très proche dans sa syntaxe de HTML (tous deux des déclinaisons de XML). Comme HTML le SVG permet de définir un ensemble de balises (rect
circle
path
…) afin de dessiner des formes plus ou moins complexes de les combiner (masque fusion…) les colorer (pleins dégradés motif) ou même gérer des filtres (flou sépia noir et blanc etc.). La plupart de ces valeurs pouvant être modifiées et le rendu SVG se faisant à la volée profitons-en pour créer des animations.
Préparer l’animation
Pour faire simple nous allons commencer par animer une seule forme (un path
). Un path
étant composé de multiples points il faut savoir que l’animation ne pourra se dérouler correctement que si le nombre de points reste identique d’une forme à l’autre il faudra donc le prendre en compte quand nous dessinerons les différentes étapes de l’animation.
Prenons les différentes formes connues d’un jeu de cartes : le cœur le pique le carreau et le trèfle. Il paraît évident qu’ils n’ont pas besoin du même nombre de points pour être dessinés par exemple :
…il faudra donc ruser et ajouter des points ici et là…
Un conseil : commencez par la forme la plus complexe pour n’avoir qu’à déplacer des points existants sur les formes plus simples. Ici j’ai donc commencé par le trèfle puis je l’ai déformé.
Une fois toutes ces formes mises en place nous allons pouvoir définir l’animation qui les lie les unes aux autres.
Animer en HTML/SVG simple et efficace
Une première technique qui tire parti des meilleures possibilités de SVG reste d’utiliser la balise <animate>
. Celle-ci prend plusieurs attributs dont :
attributeName
permet de définir l’attribut dont la valeur va changer ;dur
correspond à la durée de l’animation ;repeatCount
nous donne le nombre d’occurrences de l’animation ;values
correspond aux différentes valeurs à appliquer à l’attribut dynamique.
Dans notre cas nous aurons donc besoin des valeurs suivantes :
repeatCount="indefinite"
pour faire boucler l’animation ;attributeName="d"
oùd
est l’attribut correspondant aux coordonnées d’unpath
SVG ;- une durée ;
- et enfin une liste de différentes valeurs.
Séparées par un ;
(attention à ne pas en mettre à la fin de la liste ça ne fonctionnera pas) les différentes valeurs correspondent à chacun des SVG que nous avons créés plus tôt plus précisément cette partie-là :
Nous aurons donc :
<animate id="animation" repeatCount="indefinite" attributeName="d" dur="5s" values="...;...;...;...">
Une fois la liste des valeurs remplie vous pouvez afficher le SVG dans votre navigateur préféré et voir l’animation se lancer sous vos yeux ébahis.
See the Pen Full SVG Animation by Victor Darras (@victordarras) on CodePen.
Animer en CSS verbeux et puissant (mais Chrome seulement…)
Je suis plutôt déçu par le résultat et j’aimerais plus de finesse mais la balise <animate>
ne suffira pas. J’ai maintenant deux choix pour affiner mon contrôle utiliser du JavaScript ou du CSS. Pour ce premier exercice d’animation je vais rester au CSS qui utilise les même bases que nous avons vu mais offre plus de souplesse.
Reproduisons à l’identique notre animation avec un peu de SVG et des @keyframes
CSS.
Nettoyer le SVG
Nous n’avons plus besoin de définir les coordonnées (d
) de path
nous les définirons en CSS. Nous déclarons juste un SVG avec un path
vide.
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 124 124"> <path></path> </svg>
Dessiner les formes étapes par étapes
Pour chaque étape nous allons définir une forme dans une keyframe avec une propriété d
qui prendra pour valeur les coordonnées de la forme dans la valeur dans la fonction path('...')
comme ceci :
@keyframes cardAnim { 0% 100% { fill: tomato; d: path('M53.8367971 98.0105931 C62.5709372 90.6149791 66.2112484 87.5325537 70.0435525 83.9893009 C72.7823134 81.4571109 75.6191301 78.6895642 80.4832815 73.9441868 C92.1537616 62.5586791 96.1292776 60.2840306 102.768438 50.2737766 C109.407598 40.2635227 109.562285 19.9893997 97.8949026 8.83310282 C86.2275205 -2.32319407 65.6287893 -3.34048116 53.8367971 12.6102024 C42.7337698 -3.12466085 21.4090627 -3.84487569 8.62341819 8.83310282 C-4.16222634 21.5110813 -0.873759373 43.5215692 6.53796897 53.1409641 C13.9496973 62.7603591 14.192282 61.619107 27.18463 73.9441868 C40.176978 86.2692666 40.176978 86.2692666 53.8367971 98.0105931 Z'); } 25% { fill: grey; d: path('M33.615073 120.257813 C41.8452148 120.257813 58.0737305 120.257812 66.2344717 120.257813 C54.7068699 105.270508 54.7068699 105.270508 54.7068699 86.1914063 C60.3429237 100.47998 89.8928659 98.6647688 97.3043495 78.7348633 C104.715833 58.8049578 92.8137868 46.6757813 78.4317909 30.3862305 C64.049795 14.0966797 64.049795 14.0966797 49.7691932 0 C36.8961464 14.0966797 36.8961464 14.0966797 21.5699745 30.3862305 C6.2438026 46.6757813 -6.36850208 62.7075195 3.49038463 80.6308594 C13.3492714 98.5541992 38.5890174 102.720703 45.0164402 86.1914063 C45.0164402 105.270508 45.0164402 105.270508 33.615073 120.257813 Z'); } 50% { fill: tomato; d: path('M47.0733712 115.058105 C47.4100427 114.390075 51.87634 105.790536 58.6510079 95.6299408 C61.3834707 91.5318141 75.754243 73.4853618 79.5956177 69.3575656 C82.3483693 66.3995627 86.3942962 62.4442739 91.7333984 57.4916992 C85.3540489 53.2612305 76.894088 44.8198242 66.3535156 32.1674805 C55.8129433 19.5151367 49.1927962 8.79264323 46.4930745 0 C41.8278874 10.0341797 34.9431516 20.7566732 25.8388672 32.1674805 C16.7345828 43.5782878 8.12162703 52.019694 0 57.4916992 C10.8533079 66.4956055 19.5749876 74.9956055 26.1650391 82.9916992 C36.0501163 94.9858398 38.2597656 98.434082 47.0733712 115.058105 Z'); } 75% { fill: grey; d: path('M35.3673641 112.529297 C40.8809183 112.529297 51.7540512 112.529297 67.9867628 112.529297 C60.301695 102.53776 56.459161 91.1822917 56.459161 78.4628906 C67.9867628 92.5771484 93.6134579 95.8808594 102.337091 73.9023438 C111.060724 51.9238281 87.0333798 35.1298828 71.9572079 40.6386719 C82.3312313 27.3115234 76.0675595 0 51.6290829 0 C27.1906063 0 20.5890438 28.1669922 31.4425595 40.6386719 C20.8243954 35.4130859 -4.19085428 48.1464371 0.603692268 70.0234375 C5.39823881 91.9004379 31.6515438 97.9189453 46.7687313 78.4628906 C47.9750977 97.1577148 42.9697266 105.318848 35.3673641 112.529297 Z'); } }
Vous remarquerez que j’ai mis les étapes 0%
et 100%
aux mêmes valeurs (pour faire une boucle complète) et que je change aussi de couleur de remplissage avec la propriété fill
. Une fois les keyframes définies il nous faut déclarer l’animation à utiliser pour l’élément path
. Nous appelons d’abord les keyframes suivies de la durée et du type de répétition (ici à l’infini) comme pour la version full SVG.
svg path { animation: cardAnim 5s infinite; }
Maintenant j’aimerais faire en sorte de réduire le temps de transition pour pouvoir profiter au mieux du dessin de chaque étape (mieux distinguer les formes en somme). Je pourrais utiliser la valeur d’easing ease-in-out
disponible par défaut mais l’effet n’est pas assez saisissant je vais donc préférer une fonction de courbe de Bézier :
svg path { animation: cardAnim 5s cubic-bezier(0.8 0 0.2 1.2) infinite; }
Pour comparer voici la version cubic-bezier()
à gauche et la version ease-in-out
à droite :
(c’est tout de même mieux nan ?)
Ce qui au final devrait nous donner l’animation suivante :
See the Pen Card Icons Animation by Victor Darras (@victordarras) on CodePen.
C’est tout pour aujourd’hui je n’ai évidemment fait qu’un tout petit tour des possibilités d’animation en SVG je laisse à d’autres le soin d’être plus complets. J’espère vous avoir donné envie d’en voir plus et d’expérimenter un maximum pour faire briller plus encore le web de 2018. On pourrait définir des points mieux pensés pour fluidifier l’animation utiliser keyTimes
ou keySplines
pour simuler l’easing CSS ou encore utiliser une deuxième animation SVG pour les couleurs :
<animate repeatCount="indefinite" attributeName="fill" dur="5s" values="#000;#F00;#000;#F00;#000" />