Ceci est une ancienne révision du document !
A quick summary: over the past few instalments, we’ve looked at a couple of animation techniques for SVG files. First was to use the animation capabilities of CSS, which has better support across browsers but is limited to animating those properties that can be exposed via CSS (i.e. the ones that will work in the “style” attribute). This covers a lot of possibilities, but does not include many of the core attributes that are found in SVG elements, such as their coordinates or path definitions. For some cases – such as transforms – enough of SVG’s capabilities have been added to CSS for such restrictions to be nothing more than an annoyance that can be worked around. For others, however, CSS simply isn’t up to the task. That’s where SMIL comes in. It’s an older specification for animation, created around the same time as the original SVG specs, and does provide the ability to animate arbitrary attributes in SVG. It can animate the “d” attribute that makes up the shape of a path, for example – a task that can only otherwise be accomplished in the browser via JavaScript. But although SMIL is more powerful than CSS in this regard, it has never been adopted in any Microsoft browser, leading to its inexorable decline and a likely deprecation in the browsers that do support it.
Résumé rapide : durant les quelques articles passés, nous avons regardé quleques techniques d'animation pour les fichiers SVG. La première consistait à utiliser les capacités d'animation de CSS, qui a un bon support des navigateurs mais est limité pour l'animation de ces peopriétés qui peuvent être affichées via CSS (c'est-à-dire, celles qui fonctionneront dans l'attribut « style »). Ceci recouvre un grand nombre de possibilités , mais ne comprend pas beaucoup des attributs centraux que l'on trouve dans les éléments SVG, tels que leurs coordonnées ou les définition des chemins. Pour de tels cas, comme les transformations, suffisamment de possibilités ont été ajoutés à CSS pour que de telles restrictions ne soient rien d'autre qu'un désagrément qui peut être contourné. Simplement, pour les autres, CSS n'est pas fait pour cette tache.
C'est là que SMIL entre en scène. C'est une spécification ancienne pour l'animation, créée à peu près au même moment que les spécifs du SVG d'origine, et il fournit vraiment la capacité d'animer n'importe quel attribut dans SVG. Il peut animer l'attribut « d » qui suit la forme d'un chemin - un tache qui ne peut être autrement accomplie dans un navigateur que via Javascript. Mais, bien que SMIL soit plus puissant que le CSS à cet égard, il n'a jamais été adopté dans un navigateur Microsoft, l'entraînant vers son déclin inexorable et une dépréciation probable dans les navigateurs qui le supporte bien.
Given this situation, we won’t look any further at SMIL, but there are still a few tricks that can be performed with CSS that are worthy of further investigation. This time, we’re going to look at an increasingly popular animation technique which is really the result of taking a simple feature of SVG and pushing it in ways it wasn’t really intended for. It’s commonly referred to as “line animation”, although the line itself doesn’t change shape (remember, that can’t be done with CSS yet). It’s also sometimes referred to as a “self-drawing” image, which is a bit more descriptive: this technique results in a path that appears to be drawn on the screen in the same way as you would draw it with a pen. The first thing we’ll need is a path to animate. It should not have a fill, but will require a stroke. For this demonstration I’ve used Inkscape’s star tool to create an eight pointed star, then converted it to a path and roughly moved every second point inwards to give more of a cartoon gunshot appearance. I’ve given it a stroke-width of 2px and saved it using the “Optimised SVG” option in order to strip out most of the excess baggage from the file, just so that this tutorial isn’t filled with several pages of code.
Étant donnée la situation, nous n'étudierons pas plus SMIL, mais il y a encore quelques astuces qui peuvent être réalisées avec CSS qui méritent une investigation plus poussée. Cette fois, nous regarderons une technique d'animation de plus en plus populaire qui est en fait le résultat du choix d'une simple fonctionnalité de SVG, qui est poussée dans des façons pour lesquelles elle n'était pas prévue. Il est classique d'y faire référence comme étant l'« ligne animée » , bien que la ligne ne change pas de forme (souvenez-vous que ça ne peut pas encore se faire avec le CSS). Cela fait référence aussi ce qui est appelé une image « auto-dessinée », ce qui la décrit un peu mieux : cette technique consiste en un chemin qui semble être tracé sur l'écran de la même manière que si vous le traciez avec un stylo.
La première chose dont nous aurons besoin est un chemin à animer. Il ne devra pas avoir de remplissage, mais aura obligatoirement un contour. Pour cette démonstration, j'ai utilisé l'outil Étoile d'Inkscape pour créer une étoile à huit pointes, puis je l'ai convertie en chemin et j'ai déplacé grossièrement en retrait une pointe sur deux pour qu'elle ressemble plus à l'éclair d“un tir dans un dessin animé.Je lui ai donné une largeur de contour de 2 px et je l'ai sauvegardé comme une option « SVG optimisé » de façon à supprimer la plupart de l'excédent de bagages du fichier, juste en sorte que ce tutoriel ne soit pas rempli de plusieurs pages de code..
Opening the file in a text editor reveals a structure like that shown below. As you can see, it’s a pretty simple file. Even the <g> isn’t really needed, but it’s easier to leave it in place with its own transform, rather than try to manipulate the coordinates of the path to compensate for its removal. The secret to this animation technique is in the fact that SVG has a nice, simple, CSS-animatable way of drawing dashed and dotted strokes, rather than solid ones. The next step, therefore, is to introduce some dashes, defined in CSS. Note that you’ll probably have to also remove the corresponding properties from the path’s “style” attribute if you saved as a normal Inkscape file.
L'ouverture du fichier dans un éditeur de texte révèle une structure telle que celle montrée ci-dessous.
Comme vous pouvez le voir, c'est un fichier assez simple. Même le <g> n'est pas vraiment nécessaire, mais c'est plus facile de le laisser en place avec sa propre transformation, plutôt que d'essayer de manipuler les coordonnées du chemin pour compenser son retrait.
Le secret de cett etechnique d'animation réside dans le fait que SVG a un façon simple et animable avec CSS de dessiner des contours tiretés et pointillés, plutôt que des traits continus. Par conséquent, l'étape suivante est d'introduire quelques pointillés, définis dans le CSS. Notez que vous aurez aussi à enlever les propriétés correspondantes de l'attribut « style » du chemin si vous le sauvegardez dans un fichier SVG normal.
Save the file (top right) and load it directly into a web browser, and you should see something like this: The values we set in the stroke-dasharray property are used to determine the lengths of the drawn segments and gaps along the path. With our value of “10 2 3 5” the stroke will be drawn as a line segment of 10 units, followed by a gap of 2 units, then another line of 3 units and a gap of 5 units. The sequence then automatically repeats, so the next line segment is 10 units long and the next gap is 2. It runs around the path uninterrupted by corners, so a line segment (or gap) of 10 might appear as 3 units on one side of a corner and 7 on the other – look at the leftmost corner of the shape for a good example of this. If you follow the line round, taking that into account, you can see that the stroke dashes do follow the pattern we’ve set. This automatic repeating of values in the stroke-dasharray property produces a couple of neat features. The first is that any odd number of entries is effectively the same as writing a value that is twice as long, with the line and gap values swapped in the second half. So a value of “10 5 10” is the same as writing “10 5 10 10 5 10” – in other words a long line, short gap, long line then a long gap, short line, long gap. Notice that the length of the lines in the first half make up the length of the gaps in the second, and vice versa.
Sauvegardez le fichier (en haut à droite), chargez-le directement dans le navigateur Web et vous devriez voir quelque chose comme ça :
Les valeurs que nous avons réglées dans la propriété stroke-dasharray (contour en pointillé) sont utilisées pour déterminer les longueurs des segments dessinés et des espaces le long du chemin. Avec notre valeur de « 10 2 3 5 », le trait sera dessiné comme un segment de ligne de 10 unités, suivi d'un espace de 2 unités, puis une autre ligne de 3 unités et un espace de 5 unités. La séquence est automatiquement répétée ensuite, de sorte que le segment suivant a 10 unités de long et l'espace suivant 2 unités. Elle se poursuit tout au long du chemin sans s'interrompre aux angles, de sorte que un segment de ligne (ou un espace) de 10 unités peut avoir 3 unités d'un côté de l'angle et 7 de l'autre - regardez la pointe la plus à gauche, qui est un bon exemple de ceci. Si vous faites le tour en suivant la ligne, en prenant ceci en compte, vous pouvez voir que les morceaux du trait suivent le motif que nous avons paramétrés.
Cette répétition automatique des valeurs de la propriété stroke-dasharray produit une paire de fonctionnalités bien nettes. La première est que tout nombre impair de valeurs saisies est dans les faits identique à la saisie d'une valeur deux fois plus grande, avec les valeurs de lignes et d'espaces échangées dans la deuxième partie. Ainsi, une valeur de « 10 5 10 » est revient au même que la saisie de « 10 5 10 10 5 10 » - en d'autres termes, une longue ligne, un espace court, une longue ligne puis un espace long, une ligne courte, un espace long. Notez que la longueur des lignes de la première moitié donne la longueur des espaces de la seconde, et vice-versa.
The other feature – and the one we’re interested in here – is that you can collapse the value down to a single number to get equal line and gap lengths. A lone value of “10” expands to “10 10”, giving you a repeating series of lines that are 10 units long, followed by gaps that are 10 units long. In my example file, that gives you something like this: Now consider what happens if we increase the value. As the number goes up, so the visible line segments get longer – but so do the gaps. Below is a sequence of screenshots of the same image with the stroke-dasharray value set to 10, 20, 50, 100 and 500. By the time we get to 500 our first visible line segment almost covers the entire path. If we were to continue increasing the value until it is the same as the path length, it would effectively render it the same as if we didn’t have the stroke-dasharray at all. And that’s exactly what we want to do!
L'autre caractéristique - et c'est celle qui nous intéresse ici - est que vous pouvez réduire la valeur à un seul nombre pour obtenir de longueurs de ligne et d'espace égales. Une valeur unique de « 10 » équivaut à « 10 10 », vous donnant une série répétée de lignes ayant une longueur de 10 unités, séparées par des espaces de 10 unités de long. Dans mon fichier exemple, ça vous donne quelque chose comme ceci :
Regardez maintenant ce qui se passe si vous augmentez la valeur. Plus le nombre croît, plus les segments de ligne grandissent - pareil pour les espaces. Ci-dessous, une succession de copies d'écran de la même image est présentée où la valeur de stroke-dasharray est réglée à 10, 20, 50, 100 et 500.
Quand nous arrivons à 500, notre premier segment de ligne visible couvre à peu près tout le chemin. Si vous continuiez à augmenter la valeur jusqu'à ce qu'elle égale la longueur du chemin, le rendu serait identique à une absence de al propriété stroke-dasharray. Et c'est exactement ce que nous voulons faire !
You might be thinking it’s a little pointless to add a CSS property, then set it to a value that appears to have no effect, but remember that as well as the drawn line, there’s an equivalent length of gap that’s not visible because it extends beyond the end of the path. By adding another CSS property, however, we can adjust the start point of the drawn dashes, bringing our gap into play. The stroke-dashoffset property tells the browser to adjust its calculations to begin further into your stroke-dasharray sequence (note that the “px” here isn’t the same as screen pixels; rather it’s in the units of the SVG file, which are likely to be different to screen pixels due to scaling). If your dasharray is “10 5” and you set the offset to 3px then the first segment drawn will be only 7 units long, then a gap of 5, then a line of 10 and the rest continues as normal. In practice this means that setting a positive value here will “swallow” that much of the start of the stroke array, whereas a negative value will “push” the stroke array further along the path.
By adjusting the value of stroke-dashoffset we can “slide” the drawn portion of the stroke along the path. Here’s what it looks like with values of 0px, 100px, 200px, 300px. Notice that progressively larger numbers swallow more of the path, showing more of the gap at the end. As you know, setting the dasharray to the same value as the length of the path will draw the entire path. But also setting the dashoffset to that value will then swallow the drawn segment, leaving only the gap (which is also the length of the path). In other words, our path will disappear completely. With the drawn segment completely swallowed, we’re at the starting point for our animation: our path is not visible on the screen. By decreasing the dashoffset value we can make the drawn segment creep onto the screen, following the shape of the path. All we need to do, therefore, is to animate the stroke-dashoffset value (see part 75 if you need a reminder of the animation syntax):
Reload the file in your browser and you should see the effect we’re looking for – and because it’s all just CSS animation embedded directly in the SVG file, it will even work when the file is pulled into a web page via an <img> tag. Just a minute! Where did that value of 575 for the dasharray and dashoffset come from? As you’ve probably realised, that’s the total length of my path. You could theoretically get it from Inkscape via the Extensions > Visualise Path > Measure Path… extension, but that throws a Python error on my system. Alternatively you could just use trial and error: increasing the value of the dasharray until it just fills the path (which is quite easily done using the browser developer tools, if you’re familiar with them). The simplest option, though, is to ask the browser to do the hard work for you by invoking a little JavaScript. There is a method on the <path> object called getTotalLength() which will return the calculated length of the path. You can call it via the developer console in the browser, or modify your <svg> element to call the method when the file loads and display the value on screen. Here’s an example that will work for a file with a single path:
Remember that JavaScript won’t run when the document is loaded via the <img> tag, so to use the getTotalLength() method you will have to load the SVG file directly into the browser. You only need to do it once, then you can simply hard-code the value into the <style> block and remove the JavaScript code entirely. There is also an alternative to specifying the actual length of the path. You could add a “pathLength” attribute to the path, set it to a value of your choosing, then treat that value as the total length in the CSS. This basically tells the browser “I want to pretend this path is 100 units long, even though we both know it’s not, so can you just do the maths for me as needed”. A good compromise is to use JavaScript to find the actual length, then round it to the next whole number and set that value in the pathLength attribute and the CSS. That way any browser that understands pathLength will use it to give you a precise animation, and those that don’t are still using a value that’s close enough to work in most cases.
There’s one final thing to note with this approach. So far I’ve used the version of the technique you’ll most commonly find documented online, but, according to SVG expert Amelia Bellamy-Royds, the definition of stroke-dashoffset in the specification is vague enough that not all browsers behave identically. She suggests an alternative of forgetting dashoffset entirely and just animating stroke-dasharray instead. In this case, you need to include two numbers in the property as you need both the line and the gap to change together. My animation code then becomes that shown below. If you want to play around with this effect, but have the computer do a little more of the hard work for you, a discussion of this technique over on inkscapeforum.com led to one user creating an Inkscape extension that will add the CSS animation code for you. You can find the extension at https://gitlab.com/Moini/ink_line_animator/ and follow the original thread at http://www.inkscapeforum.com/viewtopic.php?f=5&t=33721
Just animating a star being drawn is a little dull, but does show you the basic approach. Although the star contains no curves, this method works equally well with any shape of path. An easy step on from this, for example, would be to replace the star with a path for some handwritten text, to produce a “self-writing” effect. Be aware, however, that sharp transitions can cause rendering artefacts depending on the miter limit. In the case of my star, for example, the corner at the start/end of the line flashes on and off as the rest of the line is drawn. It’s often better to use rounded corners and end caps to avoid this, which also helps to reinforce the illusion of the line being drawn by a pen or pencil. If you’re prepared to spend more time hand-crafting your animations there’s no reason why you shouldn’t produce a self-drawing SVG image consisting of multiple paths, each animated separately using delays to ensure that they appear in the correct order. Once your outline is drawn, some more delayed animations could fade in the fill colours, erase some of the lines, or cross-fade to a raster image. With time and effort, this technique can produce some spectacular results, and all just by moving a dashed line around.