Exemple 3 : Animated SVG Path by Matt Litherland
Notre exemple du jour n'a peut-être pas l'air très intéressant, mais ce sera l'exemple parfait pour notre sujet : animer un élément en suivant un "path" Svg défini à l'avance.
See the Pen Animated SVG Path by Matt Litherland (@mattsince87) on CodePen.
Commençons notre analyse en expédiant le HTML et le CSS, puis nous pourrons nous attaquer à la partie la plus intéressante du pen : le Javascript.
Au niveau du code SVG, le plus intéressant a remarqué est une absence : l'absence de toute balise permettant de dessiner ! Pas le moindre polygone ou path a l'horizon. Comme vous pouvez vous en douter, nous les retrouverons dans le Javascript. L'autre element intéressant est l'attribut "preserveAspectRatio", qui détermine si l'element SVG doit garder ses proportions uniformes ou non en cas de redimensionnement.
Niveau CSS, rien à signaler d'exotique, ce n'est que quelques lignes permettant de rendre la présentation graphiquement un petit peu plus accessible. Enfin, le Javascript.
Tout d'abord, il est important de noter que ce pen utilise Snap SVG, une library permettant de simplifier la création et l'animation du SVG depuis le Javascript.
J'avais fait un article il y a maintenant trois ans sur cette ressource, que vous pouvez allez lire si le coeur vous en dit : Insérez simplement vos images vectorielles dans vos webdesign avec Snap.svg. Sinon, notez simplement qu'il s d'une très bonne library, encore très active et maintenue aujourd'hui (une mise à jour du code tous les 15 jours sur github environ).
La deuxième chose que nous pouvons remarquer ici est que le Javascript se compose de trois blocs presque identiques, ce qui nous simplifiera la tâche ! Nous ne nous occuperons ici que du premier block (de la ligne 5 a la ligne 45).
-
var snapA = Snap("#svgA");
-
-
// SVG A – "Squiggly" Path
-
var myPathA = snapA.path("M62.9 14.9c-25-7.74-56.6 4.8-60.4 24.3-3.73 19.6 21.6 35 39.6 37.6 42.8 6.2 72.9-53.4 116-58.9 65-18.2 191 101 215 28.8 5-16.7-7-49.1-34-44-34 11.5-31 46.5-14 69.3 9.38 12.6 24.2 20.6 39.8 22.9 91.4 9.05 102-98.9 176-86.7 18.8 3.81 33 17.3 36.7 34.6 2.01 10.2.124 21.1-5.18 30.1").attr({
-
id: "squiggle",
-
fill: "none",
-
strokeWidth: "4",
-
stroke: "#ffffff",
-
strokeMiterLimit: "10",
-
strokeDasharray: "9 9",
-
strokeDashOffset: "988.01"
-
});
Commençons par le commenncement, la creation de l'element path qu'il nous manquait, avec Snap("#svgA");. Pas grand-chose à expliquer non plus pour la suite, le code est assez évident.
Les lignes suivantes permettant de créer cet effet de "déroulé" sur le path a l'ouverture du pen.
-
// SVG A – Draw Path
-
var len = myPathA.getTotalLength();
-
-
// SVG1 – Animate Path
-
myPathA.attr({
-
stroke: '#fff',
-
strokeWidth: 4,
-
fill: 'none',
-
// Animate Path
-
"stroke-dasharray": "12 6",
-
"stroke-dashoffset": len
-
}).animate({"stroke-dashoffset": 10}, 2500,mina.easeinout);
Nous récupérons dans la variable len la taille totale du path, puis nous l'appliquons comme "stroke-dashoffset" sur notre path. Le dashoffset permet de decaler la position du premier "creux" dans notre ligne pointille. Ensuite, nous lançons une animation pour que cette valeur devienne 10 en 2500ms, donc 2.5 secondes.
Enfin, nous arrivons à la partie permettant la création du petit cercle ainsi que son animation le long du path.
-
// SVG A – Circle
-
var CircleA = snapA.circle(32,32,16);
-
CircleA.attr({
-
fill: "#3f4445",
-
stroke: "#fff",
-
strokeWidth: 2
-
});
-
-
setTimeout( function() {
-
Snap.animate(0, len, function( value ) {
-
movePoint = myPathA.getPointAtLength( value );
-
CircleA.attr({ cx: movePoint.x, cy: movePoint.y }); // move along path via cx & cy attributes
-
}, 2500,mina.easeinout);
-
});
Je ne vous ferais pas l'affront de vous expliquer le sens des 7 premières lignes, attaquons-nous directement a la suite.
Commencons avec l'énigmatique lignes 9, setTimeout( function() {. Cette ligne permet de retarder l'exécution du code des lignes 10 à 13. Du moins en théorie. Nous pouvons voir à la ligne 14 que notre timeout n'a pas de temps défini, et que le code va donc s'exécuter immédiatement ! Je ne comprends donc pas du tout l'intérêt de ce timeout, surtout que sa suppression ne change rien à l'exécution du pen. Je vais prendre cela pour une originalité de l'auteur pour l'instant. Si vous avez une meilleure explication à me donner, je serais heureux de l'entendre en commentaires.
Ensuite, nous retrouvons la fonction Snap.animate(start, end, function, time, easing), qui permet d'interpoler une variable entre deux valeurs en suivant une fonction d'easing. Grâce à cela, nous pouvons donc "suivre" le path gracea myPathA.getPointAtLength( value ), et déplacer le cercle précisément à cet endroit !
Je m'arrête ici pour l'analyse de ce pen ! Vous pourrez tout de même noter quelques petites différences entre notre bloc A et les blocs B et C. Comment est obtenu cet effet d'apparition du path pour le bloc B ? Et comment est géré la gestion de l'orientation du triangle pour le bloc C ? Vous êtes maintenant a même de chercher et répondre seuls à ces questions !