À l’heure actuelle, le seul navigateur qui vous permettra de visualiser au mieux les exemples de ce site est Opera. Par exemple, les animations ne fonctionnent correctement que sous Opera. Sous Firefox 3.5 et inférieur, un script (FakeSmile) simule les fonctions d’animations mais beaucoup d’exemples sont buggés.
Il est grand temps de passer aux choses sérieuses. Les animations sont beaucoup plus puissantes que ce que vous avez pu voir jusque là. Il est possible de contrôler encore plus finement les animations, à tel point que la seule limite que vous aurez après avoir lu cette page sera votre imagination.
Vous connaissez déjà l’animation from to : elle permet de faire varier un attribut d’une valeur d’origine à une valeur finale. C’est la plus simple mais aussi la moins flexible, puisque vous devez connaître ces deux valeurs.
C’est un variante du from to mais à la différence que dans ce cas, on ne précise pas la valeur finale. Au lieu de cela, on indique de combien sera incrémentée (ou décrémentée) la valeur initiale. L’attribut by pourrait être traduit en français par « de combien » et peut prendre une valeur positive ou négative.
Si on indique seulement l’attribut to, on indique seulement la valeur finale. Il s’agit donc d’une animation from to sauf qu’il n’est pas nécessaire de connaître la valeur de départ. C’est très utile lorsque la valeur de from est générée dynamiquement (grâce à php par exemple) ou lorsqu’elle est modifié avant le lancement de l’animation (avec javascript par exemple).
Pour finir, voici l’animation la plus flexible, j’ai nommé by ! Flexible, puisqu’on indique la valeur à ajouter (ou enlever). Pas besoin, comme précédemment, de renseigner l’attribut from.
Rien ne vaut un petit exemple avec toutes ces animations. Comme d’habitude, rafraîchissez la page pour voir l’animation.
Néanmoins ces modes d’animations sont plutôt simple. SVG permet de définir une liste de valeurs qu’un attribut devra prendre, ainsi qu’une liste de repères temporels synchronisée avec une liste de valeurs.
On peut remplacer les attributs from, to et by par l’attribut values qui doit contenir une liste des différentes valeurs prises par l’attribut animé. Les valeurs sont séparés par des points-virgules. Rien de bien compliqué en somme.
Un détaille vous a peut être attiré l’œil. En effet, la vitesse de l’animation n’est pas constante : elle va beaucoup plus vite entre 50 et 130 qu’entre 130 et 110. Plus la distance a parcourir est grande, plus c’est rapide !
Les rares personnes qui ont implenté une horloge dans leur cerveau ont sans doute déjà compris pourquoi. Pour les autres, voici les explications .
Si vous prenez un chronomètre, vous remarquerez que chaque animation d’un repère à l’autre (donc entre deux valeurs de l’attribut values) dure exactement 3 secondes. Pourquoi 3 secondes ? C’est simplement la durée totale de l’animation (dur="15s") divisée par le nombre de phases. 15 secondes divisées par 5 phases font bien 3 secondes pour chaque phase.
Ce mode est appelé mode linéaire et est la valeur par défaut pour l’attribut calcMode que nous verrons plus tard.
Dans l’exemple précédent, la durée de chaque phase était fixée par la durée et le nombre de phases. Il est cependant possible de fixer soi-même le temps de chaque phase grâce à l’attribut keyTimes. Cet attribut contient une liste de pourcentage (séparés par des points-virgules) de temps, le temps de référence étant celui donné par l’attribut dur. Il doit y avoir le même nombre d’éléments dans les deux listes si bien que chaque valeur donnée dans values corresponde au pourcentage de temps correspondant dans keyTimes.
Désormais, c’est vous qui décidez du chronométrage de vos animations !
Travailler avec des pourcentages de temps n’est pas forcément très pratique, je l’admet. Vous pouvez vérifier que tout se passe bien avec un chronomètre. La première phase dure 0,05 × 20s, soit une seconde.
La seconde phase dure 0,3 - 0,05 soit 0,25 ou encore un quart de l’animation : 5 secondes.
La troisième 0,4 - 0,3 soit 0,1 = 10% de la durée totale : 2 secondes. Et ainsi de suite.
Ne vous ai-je pas dit que SVG, c’est beaucoup de calcul mental ?
Il existe plusieurs modes d’animation. Jusqu’à maintenant, on a utilisé le mode par défaut qui est linear (sauf pour animateMotion). Le mode d’animation se définit avec l’attribut calcMode.
Le mode d’animation paced permet une animation régulière (sans accélération ou ralentir) sur toute l’animation, et pas seulement entre les phases comme pour le mode linear.
Par conséquent, un éventuel attribut keyTimes est inutile et ne sera pas traité dans ce mode. Reprenons l’exemple de l’animation linear en mode paced.
Comme vous le voyez, la vitesse reste constante.
Ce mode est un peu particulier puisqu’il n’y a pas d’interpolation entre les différentes phases. Je vous vois tiquer. Si, si .
Pour faire simple, l’interpolation est l’opération permettant de savoir la valeur de l’attribut animé entre deux valeurs données. Par exemple, dans le cas d’une interpolation linéaire, si on fait varier un attribut de 0 à 100 pendant huit secondes, on a qu’à quatre secondes (la moitié de l’animation), l’attribut vaut la moitié soit 50. Mais ceci n’est que l’interpolation linéaire. La prochaine partie traite d’interpolation non linéaire mais non moins sympathique.
Mais en attendant la prochaine partie, revenons à nos moutons : le mode discrete. On l’utilise avec les attributs values et keyTimes. Chaque valeur de values est liée (dans l’ordre) à une valeur de keyTimes (ce dernier attribut devant obligatoirement commencer par zéro dans ce cas). Lorsqu’on arrive au temps spécifié dans l’attribut keyTimes, la valeur de l’attribut est changé avec la valeur correspondante de l’attribut values, et ainsi de suite pour les différentes valeurs de temps.
Aller, un autre petit exemple marrant : mettez cette image en plein écran et fixez la croix au milieu !
Passons maintenant aux choses sérieuses.
Le mode d’animation spline permet de faire de l’animation à interpolation non linéaire. Qu’est ce que cela veut-il dire ? Avec l’interpolation linéaire, à la moitié de l’animation, la valeur animée avait fait la moitié du chemin à parcourir (grosso modo). Avec ce nouveau mode d’animation, il est possible de faire varier l’attribut en accélérant au début, pui en ralentissant brusquement vers le milieu, pour finir par réaccélérer vers la fin.
Comment cela fonctionne-t-il ? Il s’agit en fait… de courbes de Bézier quadratiques. Vous vous souvenez ?
Trois attributs sont importants dans ce mode d’animation. D’abord, on fixe calcMode à la valeur spline. Ensuite, on définit une ou plusieurs liste de points de contrôle dans l’attribut keySplines qui seront utilisés entre les périodes de temps définies, elles, dans keyTimes.
Si on a keySplines="liste1 ; liste2 ; liste3" et keyTimes="t0 ; t1 ; t2 ; t3 alors les valeurs de liste1 seront utilisées entre t0 et t1, les valeurs de liste2 entre t1 et t2 et les valeurs de liste3 entre t2 et t3.
Reste la question principale : quelles sont les données des listes ? Chaque liste est en fait constituée de deux points de contrôle d’une courbe de Bézier quadratique, et donc de quatre valeurs : x1 et y1 pour le premier point de contrôle, x2 et y2 pour le second. Maintenant, je peux enfin vous dire où commence et où finit la courbe : respectivement en (0,0) et (1, 1). Ainsi les valeurs des listes doivent être comprises entre 0 et 1.
Nous touchons enfin au but : comment est définie l’interpolation de notre animation ! C’est simple. Imaginez une ligne tracée entre le point (0, 0) et (1, 1) : c’est l’animation correspondant à l’interpolation linéaire. Si notre courbe de Bézier s’en éloigne au dessus, on accélère. Si elle s’en rapproche en étant au dessus, on ralentit. Au contraire en dessous, si on s’en éloigne alors on ralentit et si on s’en rapproche, on accélère.
Exemple avec comme points 0.27,0.8 et 0.76,0.15 :
La ligne grise est la ligne de référence, celle de l’interpolation linéaire. Entre p0 et p1, la courbe s’éloigne au dessus de la courbe. L’animation accélère donc. Entre p1 et p2, c’est le contraire : d’une part la courbe se rapproche au dessus de la ligne puis s’en éloigne en dessous, donc le mouvement ralentit. Et pour finir, la courbe se rapproche de la ligne droite en étant en dessous : le mouvement réaccélère. Testons pour de vrai ce type d’animation :
Vous vous dites peut être que c’est cool mais pas très pratique. Ça serait vrai si un magnifique et très pratique outil n’existait pas : l’éditeur de keySpline de carto.net. Placez vos points, visualisez la vitesse (à droite) et tester votre animation ! Amusez vous bien .
Que se passe-t-il lorsque plusieurs animations agissent sur le même attribut et en même temps ? Par défaut, c’est la dernière animation dans l’ordre du document qui priment sur les précédentes, qui elles sont annulées.
L’attribut additive lorsqu’il est fixé à sum permet de changer ce comportement. Dans ce cas, les valeurs des différentes animations ainsi que la valeur d’origine de l’attribut sont additionnés.
Sur le rectangle du haut, point d’additivité. Du coup, lorsque la première animation se déclenche, l’attribut width passe à 0 puis prend de valeurs de plus en plus négatives. C’est pour ça qu’il ne s’affiche pas. Une seconde plus tard la seconde animation concernant le même attribut commence, annulant ainsi la première.
Pour le rectangle du bas, les animations sont additives. Du coup, lorsque commence la première animation, la valeur original de l’attribut width est additionnée à la valeur prise par l’animation. La taille diminue jusqu’à ce que la seconde animation débute. Les deux animations s’additionnent (en plus de la valeur de départ de l’attribut width) et donc la taille diminue et croît en même temps (mais elle croît plus vite qu’elle ne se réduit, donc ce qu’on voit, nous, c’est la taille qui grandit). À la fin, la première animation s’arrête et laisse pendant une seconde la seconde animation agir toute seule, sans lui mettre de bâtons dans les roues en faisait décroitre la taille ! C’est pour cela qu’elle va plus vite la dernière seconde.
L’attribut accumulate a un usage très restreint. Il ne sert que dans le cas d’une animation qui se répète (via les attributs repeatCount et repeatDur). S’il est fixé à la valeur sum, la valeur de départ de l’attribut lors de la répétition sera la valeur finale atteinte lors de la répétition précédente.
Bien sûr si votre animation est linéaire, la répétition ne sera pas vraiment visible !
Dans le premier chapitre sur les animations, je vous avait montré comment synchroniser le départ d’une animation avec le départ ou la fin d’une autre animation. Seulement, il y a d’autre moyens de synchronisation.
Il est possible de synchroniser une animation sur la répétition d’une autre animation, à condition bien sûr qu’elle se répète (ok vous vous en doutiez ). Et ce sur la première, la seconde ou la nième répétition. Ça fonctionne comme avec les mots-clefs begin et end mais cette fois-ci le mot-clé est repeat.
Notez qu’on peut faire truc.repeat(7) + 10s comme on peut faire machin.begin + 3s.
La seconde manière de synchroniser le départ ou la fin d’une animation est d’utiliser des évènements fournis par l’interface utilisateur comme le clic, le survol de la souris, etc. Il en existe plusieurs dont :
La différence entre un click, un mousedown et un mouseup, c’est que le click est constitué des deux évènements mousedown et mouseup. D’ailleurs ils se déclenchent dans cet ordre : mousedown, mouseup puis enfin click !
Testons toutes ces propriétés en même temps (cliquez sur le dessin) :
Bien sûr on peut réaliser ces animations avec les autres balises d’animation, mais set est intéressant. Par exemple, pour le premier d’entre eux, il n’y a ni valeur de durée ni fin précisé. Le changement est donc définitif.
Pour les deux du milieu, on utilise les évènements antagonistes.
Enfin dans le dernier cas, c’est un peu un hack. En effet il n’existe pas d’évènement mousedontmoveanymorestopmayhavepassedawaystop (traduction : le curseur s’est arrêté après avoir bougé). Il faut donc ruser en recommençant l’animation à chaque fois que la souris bouge. La durée est nécessaire. Essayez sans, le texte scintillera puisqu’à certains moments, le lecteur SVG considerera que la souris ne bouge pas, même si elle bouge. Le tout est de mettre une durée assez courte pour qu’elle est l’air de disparaître lorsqu’on arrête de bouger la souris, mais pas trop pour ne pas faire scintiller le texte. À vrai dire, cela dépend de beaucoup de choses, et notamment du matériel qui peut être différent lors de la diffusion d’un document.
La dernière manière de synchroniser les animations est l’appuie d’une touche. Mais attention, n’allez pas croire que c’est simple ! En fait, il s’agit du système d’accesskey qui était à l’origine un moyen d’améliorer l’accessibilité. Malheureusement, ça n’a pas fonctionné. Mais nous pouvons tout de même nous en servir : il suffit d’utiliser le mot-clé accessKey(caractère).
Mais comment activer une telle accesskey, pensez-vous aussitôt ? En fait tout dépend du navigateur. Vous avez la liste des raccourcis clavier dans l’article précédent.
Jusqu’à maintenant, les éléments d’animation étaient inclus dans l’élément que nous voulions animer. Sachez qu’on peut aussi écrire les éléments d’animation à part (c’est à dire plus loin dans le document) et donner l’élément à animer grâce à l’attribut XLink href. L’élément à animer aura comme valeur de l’attribut dur indefinite. De même, un lien classique peut de la même manière pointer vers une animation. Dans les deux cas, on indique l’identifiant de l’élément à activer (sans oublier le #).
Si vous cliquez sur le bouton alors que l’animation n’est pas terminée, elle reprend à zéro. Vous pourriez vouloir que l’animation ne recommence que si elle est finie, ou quelle ne recommence jamais. C’est possible grâce à l’attribut restart qui peut prendre trois valeurs :
Reprenons l’exemple précédent avec le mot-clé whenNotActive. Cliquez plusieurs fois de suite sur le bouton.
Dernier détail en ce qui concerne les animations, avec une propriété CSS. Oui ! Elle a la doux petit nom de pointer-events et sert à déterminer quelle partie d’une forme SVG sera sensible aux évènements de la souris. Les différentes valeurs que cette propriété peut prendre sont :
Il en existe quatre autre pour lesquelles la valeur de la propriété CSS visibility:visible n’a aucune influence. Un évènement peut se déclencher sur un élément invisible !
Ce chapitre touche à sa fin et à vrai dire, je n’ai plus beaucoup de choses à vous apprendre. Retenez juste à propos de l’animation déclarative qu’elle permet de faire des choses compliquées à première vue très simplement. Il suffit d’un peu d’ingéniosité !