**Last time, we looked at how to animate an SVG element using SMIL rather than CSS animations. We’ll continue with this topic for one more article, but my warnings from last time need to be repeated: although SMIL is (currently) more capable and flexible than the CSS option, Microsoft have chosen not to implement it in any of their browsers, leading to a slow but inexorable demise in support across all the browser vendors. For the time being, it still works in most browsers but, unfortunately, this is not a technology to bet on in the long term.
I much prefer SMIL to CSS animations. I find the code easier to understand, and the fact that the animation data tend to live inside the elements they’re animating avoids any confusion as to which rules apply to which objects as your document becomes more complex.**
La dernière fois, nous avons regardé comment animer un élément SVG en utilisant SMIL à la place des animations du CSS. Nous continuerons sur ce sujet pour un article de plus, mais mes avertissements du mois dernier doivent être répétés : bien que SMIL soit (actuellement) plus puissant et plus flexible que l'option du CSS, Microsoft a choisi de ne l'implémenter dans aucun de ses navigateurs, conduisant à un abandon lent mais inexorable de son support par tous les fournisseurs de navigateurs. À l'heure actuelle, il fonctionne encore dans la plupart des navigateurs mais, malheureusement, ce n'est pas une technologie sur laquelle parier à long terme.
Je préfère de beaucoup les animations SMIL à celles du CSS. Je trouve le code plus facile à comprendre et le fait que les données d'animation tendent à vivre dans les éléments qu'elles animent évite toute confusion concernant quelles règles s'appliquent à quels éléments, au fur et à mesure que votre document devient plus complexe.
**With a complex document it becomes ever more likely that your animations won’t all have to run at the same time, but instead might run sequentially – or a mixture of both. Consider trying to animate something as sophisticated as a cartoon: being able to finely adjust the timing of each character’s movements is essential. CSS animations offer little to help you in this case, other than the brute-force option of adding a delay to your animations with this the sort of approach (shown right).
Here we’re changing the fill color of a pair of rectangles (with IDs of “rect1” and “rect2”). The first changes from red to blue over 3 seconds. After a 3 second delay, the second rectangle changes from red to white over a 5 second period. Due to that 3 second delay, the animations occur sequentially.**
Avec un document complexe, il devient toujours plus probable que vos animations ne devront pas toutes tourner en même temps mais plutôt en séquence - ou un mélange des deux. Imaginez que vous essayez d'animer quelque chose d'aussi sophistiqué qu'un dessin animé : être capable d'ajuster finement la séquence temporelle des mouvements de chaque personnage est essentiel. Les animations du CSS n'offrent pas grand chose pour vous aider dans ce cas, à part l'option brutale d'ajouter un retard dans vos animations, avec ceci comme sorte d'approche (montré à droite).
Ici, nous avons changé la couleur de remplissage d'une paire de rectangles (avec les repères « rect1 » et « rect2 »). Le premier passe du rouge au bleu en 3 secondes. Après un retard de 3 secondes, le second rectangle passe du rouge au blanc dans une période de 5 secondes. Du fait du retard de 3 secondes, les animations ont lieu séquentiellement.
**Now what happens if you want to change the length of the first animation? You must also keep the delay for the second animation synchronised to the same value, otherwise it will either overlap the first, or occur some time after the first has finished. CSS does now support variables, so you can set the animation length once and reuse it as necessary, but the syntax is ugly and unwieldy (previous page, bottom right).
Now imagine what your CSS would look like when you want to chain five animations, or ten – or a hundred! How much better it would be if you could just tell the second animation that it should start when the first one finishes. With SMIL, that’s exactly what you can do. The SMIL animation elements have an optional “begin” attribute which allows various ways of defining when the animation should start. At its simplest, you can just enter a delay, giving the same effect as the CSS animation above (shown top right).**
Mais que se passe-t-il si vous voulez changer la durée de la première animation ? Vous devez aussi la maintenir synchronisée avec la même valeur de retard de la seconde animation. Autrement, soit elle va empiéter sur la première, soit arriver quelques instants après sa fin. CSS supporte maintenant les variables ; aussi, vous pouvez régler une fois la durée de l'animation et la réutiliser autant que nécessaire, mais la syntaxe est horrible et lourdingue (page précédente, en bas à droite).
Maintenant, imaginez à quoi ressemblerait votre CSS si vous vouliez chaîner cinq animations, ou dix, ou une centaine ! Ce serait beaucoup mieux si vous pouviez dire à la seconde animation de commencer quand la première finit. Avec SMIL, c'est exactement ce que vous pouvez faire. Les éléments de l'animation SMIL ont un attribut optionnel « begin » qui permet de définir de façon variée le début de l'animation. Dans sa forme la plus simple, il vous suffit de saisir un retard, donnant le même effet qu'avec l'animation CSS ci-dessus (montré en haut à droite).
**But you can also define the beginning of an animation to be triggered by the end of another by using the ID of the other animation, followed by “.end” (bottom right).
What happens if we want to change the length of the first animation now? No problem! Just modify the “dur” attribute and the second animation will still dutifully follow after the end of the first one. As well as the “.end” syntax you can also use “.begin” to link animations together so that they always start at the same time. You can optionally add an offset, such as “anim1.begin+2s” to make the animation begin 2 seconds after “anim1” starts, or even “anim1.end-0.5s” if you want your animation to begin half a second before the end of “anim1”.**
Mais vous pouvez aussi décider que le début d'une animation sera déclenché par la fin d'une autre en utilisant l'identifiant (ID) de cette autre animation, suivi de .end (en bas, à droite).
Qu'arrive-t-il maintenant si vous changez la durée de la première animation ? Aucun problème ! Modifiez simplement l'attribut « dur » et la seconde animation suivra encore consciencieusement la fin de la première. Tout comme la syntaxe « .end », vous pouvez aussi utiliser « .begin » pour lier ensemble deux animations de sorte qu'elles démarrent toujours en même temps. Vous pouvez ajouter un décalage optionnel, tel que « anim1.begin+2s » pour que l'animation commence deux secondes après le début d'« anim1 », ou même « anim1.end-0.5s » si voulez que votre animation commence 0,5 secondes avant la fin d'« anim1 ».
**SMIL allows animations to be repeated by adding a “repeatCount” or “repeatDur” attribute. For example, repeatCount="5" would cause the animation to repeat five times, whilst repeatDur="01:00" would cause it to repeat for one minute. When a repeating animation is used as the trigger for a second animation, this also allows an additional syntactic form to be used: begin="anim1.repeat(2)" would cause the second animation to begin immediately after the second repeat of anim1 completes. Again, changes to the duration or start time of anim1 are automatically handled for you.
In theory, these values can also be used for the “end” attribute, rather than for “begin”. That should allow you to specify that a second animation should finish three seconds after the end of the first animation, with the browser calculating when the animation should start in order to produce that result. Similarly, you should be able to specify values for “begin” and “end” with no duration set. In practice browsers fail to honor anything but a simple time-based “end” value.**
SMIL permet la répétition des animations en ajoutant un attribut « repeatCount » ou « repeatDur ». Par exemple, repeatCount="5" entraînerait cinq répétitions de l'animation, tandis que repeatDur="01:00" provoquerait la répétition de l'animation pendant une minute. Quand une animation répétée est utilisée comme déclencheur d'une seconde animation, ceci permet aussi l'utilisation d'une seconde forme syntaxique : begin="anim1.repeat(2)" entraînera le démarrage immédiat de la seconde animation après la fin de la deuxième répétition d'anim1. À nouveau, les modifications de la durée ou de l'instant de départ de anim1 sont automatiquement gérées à votre place.
En théorie, ces valeurs peuvent aussi être utilisées avec l’attribut « end », plutôt qu'avec « begin ». Ceci devrait vous permettre de spécifier que la seconde animation doit se terminer trois secondes après la fin de la première animation, le navigateur calculant quand l'animation devrait commencer pour produire ce résultat. De la même façon, vous devriez pouvoir spécifier des valeurs de « begin » et « end » sans durée établie. En pratique, les navigateurs n'arrivent à traiter qu'une simple valeur « end » basée sur le temps.
**Speaking of features that don’t work in the browsers, the “begin” (and “end”) attributes can, theoretically, take several other forms. You should be able to use an ISO8601 format time or datetime value to trigger your animation at a particular absolute time, but I was unable to get that to work in a browser. Another option is an “accessKey” - i.e. a single key on the keyboard that, when pressed, would trigger the start of the animation. The presence of a demo for this on the Mozilla developer site suggests it used to work, but neither Firefox nor Chrome behaved as expected in my own tests.
There’s one final option that does sort-of work, however: events. The following syntax, for example, will (in principle) trigger an animation when the rectangle is clicked on:
**
À propos des fonctionnalités qui ne marchent pas dans les navigateurs, les attributs « begin » (et « end ») peuvent théoriquement prendre plusieurs autres formes. Vous devriez pouvoir utiliser une valeur d'heure ou de date au format ISO8601 pour déclencher votre animation à un instant absolu particulier, mais j'ai été incapable de le faire fonctionner dans un navigateur. Une autre option est une « accessKey » (touche d'accès) - par exemple, une simple touche du clavier qui, quand elle est enfoncée, déclencherait le début de l'animation. La présence d'une démo de ceci sur le site des développeurs de Mozilla suggère que ça marchait dans le passé, mais ni Firefox, ni Chrome, ne se sont comportés comme attendu, dans mes propres tests.
Il y a cependant une dernière option qui fonctionne plus ou moins bien : les événements. La syntaxe suivante, par exemple, déclenchera (en principe) une animation quand on clique sur le rectangle :
**There are various events available, covering not only clicks but also mouse movements, scrolling and even changes to the structure of the document. Although the example above uses the parent element to trigger the animation, in practice you could use the ID of another element in the image – allowing a click on one element (styled as a Start button, perhaps) to trigger an animation on another.
In practice this option does work, but only in situations when JavaScript would also be executed: when the SVG image is loaded directly, via an