[Plan du site]
Vous êtes ici ---
> Le Site du Zéro
> Les tutoriels
> Non-Officiels
> Graphisme
> Divers
> Le SVG > Les graphiques vectoriels > Les animations
> Lecture du tutoriel
Les animations
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Dans ce chapitre, nous verrons comment
animer vos formes !
Nous apprendrons comment réaliser la plupart des transformations géométriques possibles, ainsi que des changements de couleurs, etc.
Le SVG possède cinq balises pour définir des animations. Nous les verrons en détails.
Malheureusement, Firefox ne gère pas les animations.
Je sais que ce chapitre est long, C'est pourquoi je vous recommande de le lire en deux coups. Par contre, ce que nous apprenons dans la première sous-partie sera réutilisé dans les quatre autres.
Théoriquement, une animation est le changement de la valeur d'un attribut, ou d'une propriété CSS, au cours du temps.
La première balise que je vous présente est <animate />, car c'est la plus polyvalente. Elle a un grand nombre d'attributs, et je crois que la meilleure façon de vous les présenter est de partir d'un exemple concret.
Disons donc que nous avons un rectangle,
Code : XML1
2
3 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;" />
...
|
et que nous voulons lui faire faire une translation horizontale de 140 pixels vers la droite.
Comment allons-nous procéder ?
Nous allons tout simplement changer la valeur de son attribut
x au cours du temps.
Et ce qu'il y a de merveilleux avec le SVG, c'est que, contrairement aux gif animés, on n'a pas besoin de dessiner toutes les images de l'animation.
Par exemple, pour notre rectangle, on indiquera les valeurs de départ et d'arrivée de l'attribut x, et le programme dessinera toutes les autres images tout seul.
Commençons. Comme je vous l'ai dit, on se servira de la balise <animate />.
On a donc déjà ça :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;" />
<animate />
...
|
Maintenant, comment faire savoir au programme que c'est le rectangle "rectangleQuiBouge" qui sera animé ?
1 - Pour indiquer la balise cible de l'animation
Nous avons 2 choix.
Maintenant, comment allons-nous faire savoir que c'est l'attribut x de notre rectangle dont nous voulons changer la valeur ?
2 - Pour indiquer l'attribut ou la propriété-cible de l'animation
Cette fois, nous aurons recours à deux attributs de la balise <animate />. Le premier est attributeName. On lui donne comme valeur le nom de l'attribut ou de la propriété CSS dont nous voulons faire changer la valeur. Dans notre exemple, on mettrait donc :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate attributeName="x" />
</rect>
...
|
Mais il faut aussi mettre un deuxième attribut, attributeType. Comme valeur, vous mettez
CSS si la valeur de attributeName est une propriété CSS, et vous mettez
XML si, comme dans notre exemple, c'est un attribut d'une balise SVG. On aurait donc :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate attributeName="x" attributeType="XML" />
</rect>
...
|
<animate /> permet de changer la valeur d'
un attribut seulement. Si vous vouliez faire une translation diagonale, il vous faudrait changer et
x et
y ; vous auriez donc deux balises <animate /> à créer.
3 - Pour indiquer les valeurs de début et de fin de l'attribut (ou la propriété) cible
La prochaine chose à faire est de faire savoir au programme que nous voulons que notre rectangle parte du point (60,30) pour se rendre au point (200,30). Pour ce faire, nous aurons recours aux attributs
from et
to de la balise <animate />. Pour
from (de, en anglais), vous indiquez la valeur de départ de
x (pour nous 60), et dans
to (vers, en anglais), vous indiquez la valeur de fin de
x (pour nous 200) :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate attributeName="x" attributeType="XML" from="60" to="200" />
</rect>
...
|
Si vous essayez ce code, il ne se passe toujours rien. Pourquoi ? Car, entre autres, vous n'avez pas spécifié
quand l'animation doit commencer.
4 - Pour contrôler la synchronisation de l'animation
I - Le début de l'animation
Prochaine étape : indiquer le début de l'animation. Nous allons réaliser ceci grâce à l'attribut begin (en anglais, commencement).
Il existe plusieurs façons d'indiquer le début d'une animation, mais commençons par la plus simple.
Il s'agit ici d'indiquer un temps par rapport à la fin du chargement (loading) de votre document SVG par le programme. Pour indiquer un temps, vous pouvez utiliser trois syntaxes différentes :
Pour en revenir à notre rectangle, on aurait donc :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate attributeName="x" attributeType="XML" from="60" to="200" begin="5s" />
</rect>
...
|
Si vous essayez ce code, ça ne marche toujours pas. Il manque encore un attribut essentiel.
II - La durée de l'animation
Il faut faire savoir au programme en combien de temps le rectangle doit se déplacer du point (60,30) vers le point (200,30). On fait ceci avec l'attribut dur (abréviation de duration, durée en anglais). On indique un temps, comme on a appris à le faire avec begin :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate attributeName="x" attributeType="XML" from="60" to="200" begin="5s" dur="3s"/>
</rect>
...
|
Et voilà ! Notre beau rectangle se déplace tout seul ! Le seul inconvénient, c'est qu'il revient à son point de départ à la fin de l'animation

. C'est ce que vous vouliez ? Pas de problème

. Sinon, voyons comment y remédier

.
III - L'attribut fill
L'astuce est de rajouter à la balise <animate /> un autre attribut,
fill, avec une valeur de
freeze. Cela aura l'effet de "geler" l'animation en position finale (d'où le freeze, geler en anglais). Par exemple, pour que notre rectangle reste en position à la fin de sa translation, nous écririons :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate id="bougageDuRectangle" attributeName="x" attributeType="XML" from="60" to="200" begin="5s" dur="3s" fill="freeze" />
</rect>
...
|
La valeur par défaut de
fill est
remove. L'effet obtenu serait exactement le même que si on ne mettait pas d'attribut
fill du tout : notre rectangle ferait sa translation, puis reviendrait à son point de départ.
Et voilà ! Vous venez de terminer votre première animation !
Mais nous sommes loin d'avoir exploré toutes les possibilités que <animate /> nous offre !
V - L'attribut end
C'est un attribut qui sert à indiquer, à l'aide d'un temps, la fin de l'animation.
Mais... la fin de l'animation est calculée comme étant
begin +
dur, non ?
En effet. Si vous indiquez dans
end une valeur plus petite que
begin +
dur, l'animation stoppera à ce moment-là. Bon. Je comprends que vous ne voyiez pas vraiment l'utilité de
end pour l'instant, mais... patientez. Cette balise nous sera utile très bientôt. Sachez seulement qu'elle peut arrêter l'animation.
IV - Autres manières d'indiquer le début ou la fin d'une animation
Je vous ai dit plus tôt qu'il y avait plusieurs façons d'indiquer le début d'une animation, avec l'attribut
begin. Nous allons maintenant en voir trois supplémentaires.
Synchronisation sur d'autres animations
La première méthode que je vous montre ici consiste à indiquer le début d'une animation par rapport au début ou la fin d'une autre animation. Dans ce cas-là, il faudra donner un id à l'animation de référence. Dans begin, on écrirait, par exemple :
Code : XML1
2
3 | ...
<animate attributeName="x" attributeType="XML" from="60" to="200" begin="animationDeReference.end+2s" dur="3s" fill="freeze" />
...
|
Cela aurait pour effet de commencer l'animation 2 secondes après la fin de l'animation dont l'id est "animationDeReference".
Le
.end signifie la fin de l'animation. Vous pourriez aussi écrire
.begin, ce qui voudrait dire de calculer à partir du début de
animationDeReference.
Et vous n'êtes pas obligés d'écrire le +2s. Si vous n'écrivez que
animationDeReference.end, cela aurait pour effet de commencer l'animation immédiatement à la fin de
animationDeReference.
Bon. Je crois qu'il est temps pour un petit TP.
Vous allez ajouter à notre fichier rectangle un cercle rouge au trait orange, de rayon 15 et situé à (50,70). Ce cercle fera une translation verticale de 100 pixels vers le bas. Cette animation commencera 3 secondes après le début de la translation du rectangle.
Êtes-vous prêts ?
...
Attention !
3, 2, 1, à vos Bloc-notes !
...
...
...
Vous voulez la correction ?
Secret (cliquez pour afficher)
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="800" height="800" version="1.1" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg">
<title>Rectangle et cercle qui bougent</title>
<defs>
</defs>
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate id="bougageDuRectangle" attributeName="x" attributeType="XML" from="60" to="200" begin="2s" dur="3s" fill="freeze" />
</rect>
<circle id="cercleQuiBouge" cx="50" cy="70" r="15" style="fill: #F70701; stroke: #FFA200;">
<animate attributeName="cy" attributeType="XML" from="70" to="170" begin="bougageDuRectangle.begin+2s" dur="3s" fill="freeze" />
</circle>
</svg>
|
N'oubliez pas de rajouter un id à l'animation du rectangle :
Code : XML1
2
3 | ...
<animate attributeName="cy" attributeType="XML" from="70" to="170" begin="bougageDuRectangle.begin+2s" dur="3s" fill="freeze" />
...
|
Mais cette méthode fonctionne aussi avec l'attribut
end. La syntaxe est la même que pour
begin :
Code : XML1 | <animate ... end="bougageDuRectangle.begin+4s" ... />
|
Cette méthode vous sera utile si vous avez plusieurs animations qui doivent se déclencher, par exemple, à 2 secondes d'intervalle. Avouez qu'il est plus facile d'écrire
id.end+2s que de calculer à la main chaque temps de début.
Synchronisation sur des événements souris
La deuxième méthode dont je vous parle est encore plus intéressante. Elle permet de commencer (avec
begin) ou de terminer (avec
end) une animation par rapport à un événement. Par événement, j'entends toute action de la souris : lorsqu'on clique sur une forme, lorsqu'on en survole une autre, etc.
Le principe est le même que pour la méthode précédente : vous devez indiquer dans
begin ou dans
end un id de référence, suivi d'un point (.) et finalement d'un événement :
Code : XML1 | <animate ... begin="id.evenement+2s" ... />
|
Il y a plusieurs événements différents. Les voici :
- click : survient quand la souris clique sur la forme de référence ;
- activate : même chose que click ;
- mousedown : survient quand le bouton de la souris est enfoncé sur la forme ;
- mouseup : survient quand le bouton de la souris est relâché sur la forme ;
- mouseover : survient quand la souris survole la forme ;
- mouseout : survient quand le curseur de la souris "sort" du dessus de la forme ;
- mousemove : survient quand la souris bouge alors qu'elle était sur la forme.
Deuxième petit TP : vous reprenez votre fichier du rectangle et du cercle et vous le modifiez pour que l'animation du cercle commence lorsque la souris survole le rectangle. Vous faites aussi en sorte que l'animation du rectangle stoppe lorsque l'on clique sur le cercle.
Ready ?
...
Go !
...
...
...
On corrige !
Secret (cliquez pour afficher)Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="800" height="800" version="1.1" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg">
<title>Rectangle et cercle qui bougent et interragissent !</title>
<defs>
</defs>
<rect id="rectangleQuiBouge" x="60" y="30" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animate id="bougageDuRectangle" attributeName="x" attributeType="XML" from="60" to="200" begin="2s" end="cercleQuiBouge.click" dur="3s" fill="freeze" />
</rect>
<circle id="cercleQuiBouge" cx="50" cy="70" r="15" style="fill: #F70701; stroke: #FFA200;">
<animate attributeName="cy" attributeType="XML" from="70" to="170" begin="rectangleQuiBouge.mouseover" dur="3s" fill="freeze" />
</circle>
</svg>
|
Et voilà ! Vous auriez aussi pu utiliser
activate à la place de
click, dans l'attribut end du rectangle.
Synchronisation sur des événements clavier
Il est aussi possible de faire commencer (mais pas terminer) une animation lorsque l'utilisateur appuie sur une touche particulière du clavier.
Pour ce faire, la syntaxe à utiliser dans
begin est la suivante :
begin="accesKey(touche)".
accesKey est en anglais et signifie "touche d'accès". Facile, non ? Bien sûr, à la place de
touche, vous mettez la touche du clavier à appuyer pour commencer l'animation : s, w, 8, ?, ou ce que vous voulez :
Code : XML1
2
3
4
5 | ...
<rect id="rectangleQuiBouge" x="60" y="30" width="110" height="150" style="stroke: #0B24BE; fill: #18C20B;">
<animate attributeName="x" attributeType="XML" from="60" to="200" begin="accessKey(y)" dur="3s" fill="freeze" />
</rect>
...
|
Ici, la translation commencerait lorsque l'on appuierait sur la touche "y".
Mais attention ! Vous ne pouvez pas mettre de <, >, et autres signes qui pourraient confondre le programme. Si vous tenez vraiment à les utiliser, vous devez mettre leur code d'entité ASCII. Une liste de ces entités est disponible
ici. (La colonne de gauche est le caractère, et celle à l'extrême droite, son code d'entité ASCII.)
V - L'attribut restart
Cet attribut peut prendre trois valeurs :
- always (valeur par défaut) : l'animation peut être recommencée à tout moment ;
- never : l'animation ne peut jamais être recommencée ;
- whenNotActive : l'animation ne peut être recommencée que lorsqu'elle est terminée.
Si vous reprenez votre fichier "Rectangle et cercle qui bougent et interagissent !", et que vous ajoutez
restart avec la valeur
whenNotActive dans l'animation du cercle, comme ceci :
Code : XML1
2
3 | ...
<animate attributeName="cy" attributeType="XML" from="70" to="170" begin="rectangleQuiBouge.mouseover" dur="3s" fill="freeze" restart="whenNotActive" />
...
|
vous verrez que même si vous survolez le rectangle, vous ne pouvez pas recommencer l'animation du cercle si elle n'est pas terminée.
Conclusion
Et voilà. Je sais que cette sous-partie était un gros morceau, car nous avons vu plusieurs choses d'un coup. Mais ne vous inquiétez pas, nous allons réutiliser une très grosse majorité des attributs que nous venons de voir pour les autres balises d'animation.
<set /> est une balise très simple.
Contrairement à <animate />, elle ne peut pas calculer et dessiner les valeurs comprises entre les valeurs de début et de fin de son attribut-cible, et elle n'a donc pas d'attribut
dur.
Quelle est donc son utilité, me direz-vous ?
La plupart du temps, elle est utilisée pour cacher une forme ou l'afficher. Pour ce faire, on utilise une propriété CSS,
visibility, qui peut avoir trois valeurs :
- visible : la forme est affichée ;
- hidden ou collaspe : la forme est cachée, elle n'est pas dessinée.
visibility: hidden ne produit pas le même effet que opacity: 0. En effet, l'utilisation de visibility empêche la forme de pouvoir recevoir des événements (clicks, survols, etc.).
Un petit exemple pour bien comprendre :
Code : XML1
2
3
4
5
6
7
8
9 | ...
<ellipse cx="300" cy="300" rx="70" ry="30" style="fill: #26B90E; stroke: #9A0E9F;">
<set attributeName="visibility" attributeType="CSS" to="hidden" begin="triangle.click" />
<set attributeName="visibility" attributeType="CSS" to="visible" begin="triangle2.click" />
</ellipse>
<path id="triangle" d="M70`40 l-20`30 l40`0 z" style="fill: #F6FF00; stroke: #2B77D5;" />
<path id="triangle2" d="M120`40 l20`30 l20`-30 z" style="fill: #2B77D5; stroke: #F6FF00;" />
...
|
Appuyer sur le triangle jaune "cachera" la forme, alors que cliquer sur le bleu l'affichera. Bien sûr, vous n'êtes pas obligés d'utiliser des événements dans begin. Un temps fonctionnerait aussi.
Comme vous voyez, on a utilisé les mêmes attributs que pour <animate />, ce qui sera aussi le cas, à peu de choses près, pour les trois autres balises d'animation.
Dans la première partie de ce chapitre, nous avons réalisé une translation simple : un seul attribut de notre rectangle était modifié. Je vous avais dit que si vous vouliez faire une translation diagonale, vous auriez à insérer deux balises <animate />.
Mais imaginez que vous vouliez faire effectuer une translation comportant des courbes... Il vous serait impossible de le faire avec <animate />. C'est pourquoi il existe une balise qui permet ce genre de translation : <animateMotion /> (motion veut dire mouvement en anglais).
Elle est un peu différente, par contre. Entre autres, elle introduit un nouvel attribut :
path. C'est grâce à lui que l'animation pourra se déplacer sur des courbes. En effet, nous allons écrire dans cet attribut un tracé, comme on a appris à le faire dans le chapitre Les formes. C'est sur ce tracé que notre forme se déplacera. (On l'appellera alors tracé de mouvement.) Il n'y aura donc pas d'attributs
from et
to, ni d'
attributeName et d'
attributeType.
Par contre, nous utiliserons
begin et
dur, comme avec <animate /> :
Code : XML1
2
3
4
5
6
7 | ...
<path d="M200`200 c150`-50 100`200 200`200 s0`-100 100`-200" fill="none" stroke="black" />
<path id="triangleQuiBouge" d="M200`200 l50`50 l25`-49 z" style="fill:#A23333; stroke: #2439AB;">
<animateMotion begin="0s" dur="5s" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" fill="freeze "/>
</path>
...
|
Ici, j'ai inclus un tracé au début de mon code, pour que l'on voie mieux comment la forme bouge.
Les coordonnées de l'attribut path sont calculées à partir du moveto de triangleQuiBouge. Vous devez donc mettre 0,0 comme premier moveto de l'attribut path.
Et c'est également le premier moveto de triangleQuiBouge qui se déplace sur le tracé. Si c'était un rectangle, ce serait son coin supérieur gauche (indiqué avec
x et
y), et si c'était un cercle ou une ellipse, ce serait son centre (coordonnées indiquées avec
cx et
cy).
La balise <mpath />
Supposons que vous vouliez faire effectuer le même tracé de mouvement à plusieurs formes. Bien sûr, vous pourriez indiquer le même tracé de mouvement dans les attributs
path des balises <animateMotion /> de toutes nos formes, comme ceci :
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | ...
<path d="M20`20 l50`50 l25`-49 z" style="fill:#A23333; stroke: #2439AB;">
<animateMotion begin="0s" dur="5s" fill="freeze" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</path>
<ellipse cx="150" cy="150" rx="70" ry="30" style="fill: #26B90E; stroke: #9A0E9F;">
<animateMotion begin="0s" dur="5s" fill="freeze" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</ellipse>
<rect x="360" y="130" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animateMotion begin="0s" dur="5s" fill="freeze" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</rect>
<circle cx="150" cy="270" r="15" style="fill: #F70701; stroke: #FFA200;">
<animateMotion begin="0s" dur="5s" fill="freeze" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</circle>
...
|
Mais il existe une autre méthode, qui diminuera la taille de vos fichiers.
Nous n'allons pas inclure d'attribut
path dans nos balises <animateMotion />. Par contre, nous allons ajouter une balise fille <mpath /> à chacune de nos quatre balises <animateMotion />. Elle deviendront alors des balises doubles : <animateMotion>...</animateMotion>.
Les balises <mpath /> n'auront qu'un seul attribut,
xlink:href. Comme valeur, vous mettrez l'id d'un tracé que vous inclurez dans <defs>, précédé d'un dièse.
Il ne faudra donc pas oublier de rajouter le namespace de XLink dans la balises <svg>. (Si vous ne vous souvenez plus de XLink et des namespaces, allez relire
la sous-partie sur les motifs du chapitre précédent, lorsque je parle des images bitmap.)
Au final, cela nous donnerait ceci :
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | ...
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="800" height="800" version="1.1" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Modele</title>
<defs>
<path id="bellePetiteCourbe" d="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</defs>
<path d="M20`20 l50`50 l25`-49 z" style="fill:#A23333; stroke: #2439AB;">
<animateMotion begin="0s" dur="5s" fill="freeze">
<mpath xlink:href="#bellePetiteCourbe" />
</animateMotion>
</path>
<ellipse cx="150" cy="150" rx="70" ry="30" style="fill: #26B90E; stroke: #9A0E9F;">
<animateMotion begin="0s" dur="5s" fill="freeze" >
<mpath xlink:href="#bellePetiteCourbe" />
</animateMotion>
</ellipse>
<rect x="360" y="130" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animateMotion begin="0s" dur="5s" fill="freeze" >
<mpath xlink:href="#bellePetiteCourbe" />
</animateMotion>
</rect>
<circle cx="150" cy="270" r="15" style="fill: #F70701; stroke: #FFA200;">
<animateMotion begin="0s" dur="5s" fill="freeze" >
<mpath xlink:href="#bellePetiteCourbe" />
</animateMotion>
</circle>
</svg>
...
|
Rotation sur un tracé de mouvement
Vous avez sûrement remarqué que les formes de l'exemple précédent restent droites alors qu'elles se déplacent sur son tracé de mouvement.
<animateMotion /> a un attribut pour contrôler ce comportement :
rotate. Sa valeur par défaut est de 0, et c'est pourquoi les formes ne s'inclinent pas. Si vous mettez un autre angle que 0 comme valeur de rotate, vous verrez que la forme sera inclinée de la valeur de
rotate alors qu'elle se déplace sur le tracé de mouvement.
Un exemple :
Code : XML1
2
3
4 | ...
<path d="M0`0 l50`50 l25`-49 z" style="fill:#A23333; stroke: #2439AB;">
<animateMotion begin="0s" dur="5s" fill="freeze" rotate="54" path="m0`0 c150`-50 100`200 200`200 s0`-100 100`-200" />
</path>
|
Mais l'utilité de
rotate ne s'arrête pas là. On peut aussi indiquer une valeur de
auto. Dans ce cas, la forme pivotera d'elle-même sur son tracé de mouvement au fur et à mesure qu'elle rencontre des courbes.
L'ajout de rotate avec une valeur autre qu'un angle, comme auto, change un peut le fonctionnement des coordonnées.
En effet, vous devrez mettre le moveto du tracé de mouvement non pas à m0,0, comme avant, mais plutôt à la position désirée de votre forme. Cette forme, quant à elle devra être positionnée à 0,0. Ne me demandez pas pourquoi, je cherche encore.
En exemple, on aurait donc :
Code : XML1
2
3
4
5
6
7 | ...
<path d="M200`200 c150`-50 100`200 200`200 s0`-100 100`-200" style="fill:none; stroke:black;" />
<rect x="0" y="0" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animateMotion begin="0s" dur="5s" fill="freeze" rotate="auto" path="m200`200s c150`-50 100`200 200`200 s0`-100 100`-200" />
</rect>
...
|
Au lieu de
auto, vous pouvez aussi mettre
auto-reverse. Dans ce cas, si on reprend notre code précédent, vous verrez que le rectangle pivote de l'autre côté de la courbe :
Code : XML1
2
3
4
5
6
7
8 | ...
<path d="M200`200 c150`-50 100`200 200`200 s0`-100 100`-200" style="fill:none; stroke:black;" />
<rect x="0" y="0" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animateMotion begin="0s" dur="5s" fill="freeze" rotate="auto-reverse" path="m200`200s c150`-50 100`200 200`200 s0`-100 100`-200" />
</rect>
...
|
Répétition d'animation
Nous allons maintenant voir un nouvel attribut, valable pour les cinq balises d'animation. J'aurais pu vous le montrer dans la première partie de ce chapitre, mais je pense que c'était un assez gros morceau pour vous.
Nous allons voir comment gérer la répétition des animations. Pour qu'une animation se répète, on aura recours à l'attribut repeatCount. Vous devez indiquer un nombre qui sera le nombre de fois que l'animation sera répétée. (On appelle cela le
nombre d'itérations de l'animation.) Si vous voulez que l'animation se répète à l'infini, vous mettez
indefinite.
Exemples :
Code : XML1
2
3
4
5 | ...
<rect x="0" y="0" width="30" height="20" style="fill: #0B24BE; stroke: #18C20B;">
<animateMotion begin="0s" dur="5s" repeatCount="3" fill="freeze" rotate="auto-reverse" path="m200`200 c150`-50 100`200 200`200 s0`-100 100`-200" />
</rect>
...
|
Code : XML1
2
3
4
5 | ...
<path d="M0`0 l50`50 l25`-49 z" style="fill:#A23333; stroke: #2439AB;">
<animateMotion begin="0s" dur="5s" repeatCount="indefinite" fill="freeze" rotate="auto-reverse" path="m200`200 c150`-50 100`200 200`200 s0`-100 100`-200" />
</path>
...
|
N'oubliez pas alors que l'attribut dur indique la durée d'une itération, et non de toutes.
Bien que <animate /> permette de faire certains changement de couleurs, ce n'est pas bien interprété par les programmes.
C'est pourquoi il existe une balise juste pour les changements de couleurs, <animateColor />. Elle fonctionne
exactement de la même façon que <animate /> :
Code : XML1
2
3
4
5 | ...
<polygon points="50`50 50`200 100`250 200`200 200`100 200`100 200`50" style="stroke: #0795A2; fill: #FFAE00;">
<animate attributeName="fill" attributeType="CSS" from="#FFAE00" to="#CE18D5" begin="0s" dur="10s" fill="freeze" />
<polygon/>
...
|
La couleur de remplissage du polygone passera ainsi de orange à magenta en 10 secondes.
C'est pas mal, tout ce que j'ai à dire sur <animateColor /> !
values et keyTimes
Par contre, c'est l'occasion pour nous d'apprendre deux nouveaux attributs, valables pour toutes les balises d'animations, excepté <animateMotion />.
Je vous parle ici premièrement de l'attribut
values. Il sert à indiquer
plus qu'une valeur pour l'attribut cible de l'animation. On pourrait donc faire passer le remplissage de notre forme de orange à violet, puis à rouge, et enfin à bleu, tout ça dans la même animation.
Dans
values, vous indiquez les différentes valeurs que vous désirez assigner à la propriété-cible, séparées par des points-virgules (;).
Attention ! Ne mettez pas de point-virgule après la dernière valeur :
Code : XML1
2
3
4 | ...<polygon points="50`50 50`200 100`250 200`200 200`100 200`100 200`50" style="stroke: #0795A2; fill: #FFAE00;">
<animateColor attributeName="fill" attributeType="CSS" values="#FFAE00;#CE18D5;#FF3401;#3366FF" begin="0s" dur="3s" fill="freeze" />
</polygon>
...
|
Si vous mettiez un point virgule après la dernière valeur, le programme penserait que vous voulez ajouter une nouvelle valeur, et n'en trouvant pas, il choisirait la couleur par défaut, le noir.
Il existe un attribut pour permettre de contrôler plus facilement à combien de temps les différentes valeurs de
values doivent apparaître.
Si vous vouliez par exemple, que le polygone soit déjà violet après deux secondes, puis qu'il soit rouge à six secondes et complètement bleu à dix, vous auriez recours à l'attribut
keyTimes.
À l'intérieur de celui-ci, c'est encore des valeurs séparées par des points-virgules que vous mettrez, mais cette fois des valeurs de temps. Par contre, ce sont des valeurs de temps relatives à l'animation ; la première valeur doit être 0, qui équivaut à la première valeur de
values, lorsque l'animation est à 0%, et la dernière valeur doit être 1, qui équivaut à la dernière valeur de
values, lorsque l'animation est à 100%. Entre les deux, vous indiquez des nombres à virgules ; 0.2 pour 20% de l'animation, 0.7 pour 70% de l'animation.
Pour en revenir à mon exemple, c'est-à-dire que le polygone soit violet à deux secondes, puis orange à six et bleu à dix, on écrirait :
Code : XML1
2
3 | <polygon points="50`50 50`200 100`250 200`200 200`100 200`100 200`50" style="stroke: #0795A2; fill: #FFAE00;">
<animateColor attributeName="fill" attributeType="CSS" values="#FFAE00; #CE18D5; #FF3401; #3366FF" keyTimes="0; 0.2; 0.6; 1" begin="0s" dur="10s" fill="freeze" />
</polygon>
|
Remarquez que l'on peut mettre des espaces entre les valeurs dans keyTimes ainsi que dans values, en autant que vous ne mettiez pas de point-virgule après la dernière valeur.
Faites bien attention également d'avoir le même nombre de valeurs dans values que dans keyTimes.
Allez, courage, il ne nous reste qu'une seule balise d'animation à voir !
La balise d'animation <animateTransform /> sert à effectuer des transformations géométriques.
Un minimum de connaissances en géométrie est nécessaire pour bien comprendre cette partie. Si vous vous sentez perdus, soyez plus attentifs en maths !
<animateTransform /> aussi fonctionne exactement de la même manière que <animate />. Je ne vous apprendrai donc presque rien de nouveau sur les animations. Par contre, l'attribut dont nous allons modifier la valeur dynamiquement, avec <animateTransform />, est, lui, nouveau.
Je parle ici de l'attribut
transform. Il peut s'appliquer à toutes les formes que nous avons apprises jusqu'à maintenant, ainsi qu'aux groupes d'éléments.
transform permet d'effectuer cinq transformations différentes, que nous allons voir :
- translation ;
- homothétie ;
- rotation ;
- inclinaison (sur l'axe des x ou celui des y).
Avant de nous pencher dessus, voilà approximativement ce que vous devriez déjà avoir pour essayer les animations :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" from="" to="" begin="1s" dur="5s" fill="freeze" />
</path>
...
|
Mais... ton tracé n'a même pas d'attribut transform !
Il n'en a pas car il n'en a pas besoin. En effet, nous allons modifier sa valeur par défaut, et tout se fera dans <animateTransform />
Translation
Mais... on a déjà fait des translations dans la première partie de ce chapitre, non ?! Pourquoi apprendre une autre façon ?
- Pour vous éviter d'avoir à faire des tracés de mouvements à chaque fois que vous voulez faire faire des translations simple à un tracé. (J'entends par translation simple toute translation verticale, horizontale ou diagonale.) En effet, un tracé n'a pas d'attribut x et y, ni rien d'équivalent. On ne pourrait donc pas utiliser <animate />.
- Pour vous éviter d'avoir à écrire deux balises <animate /> à chaque fois que vous voulez faire faire une translation diagonale à une forme. transform fera cela avec une seule balise <animateTransform />.
Pour faire effectuer une translation à notre tracé, nous allons d'abord placer dans <animateTransform /> le type de transformation voulue (en anglais bien sûr), à l'aide de l'attribut
type :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="" to="" begin="1s" dur="5s" fill="freeze" />
</path>
...
|
C'est dans
from et
to que nous indiquerons le vecteur de la translation
x,y.
Si nous voulons que notre tracé fasse un translation de 320 pixels vers la droite et de 240 pixels vers le bas, nous écririons :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0`0" to="320`240" begin="1s" dur="5s" fill="freeze" />
</path>
...
|
Dans transform...
Bien sûr, vous n'êtes pas obligés d'utiliser
transform uniquement pour faire des animations. En effet, cela peut être utile pour faire des ajustements. (Décaler des formes par rapport à leur positions plutôt que changer leurs attributs
x et
y.) Dans ce cas, c'est dans l'attribut
transform des formes que vous devrez indiquer le type, suivi du vecteur de la translation entre parenthèses :
Code : XML1
2
3 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" transform="translate(10`5)" style="fill:#00DA43; stroke:#28601D;">
...
|
Faites bien attention de ne pas mettre d'espace entre le type de transformation (ici translate) et les parenthèses. Sinon, le programme ne peut lire correctement l'information.
Homothétie
Une homothétie est l'agrandissement ou le rétrécissement d'une forme. Pour faire effectuer une homothétie à une forme, vous devez indiquer
scale dans l'attribut
type de <animateTransform />, et attention : dans
from, vous devez indiquer 1, car 1 signifie 100% de la forme actuelle. Tandis que dans
to, vous indiquez le facteur d'homothétie :
- soit une valeur entre 1 et 0, comme par exemple 0.5, ce qui diminuera la forme de 50%.
Faites bien attention d'écrire vos nombres décimaux avec un point (.), et non une virgule :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="0.5" begin="1s" dur="5s" fill="freeze" />
</path>
...
|
- soit une valeur plus grande que 1, comme par exemple 2.5, ce qui augmentera la forme de 250%.
Encore une fois, faites attention d'écrire vos nombres décimaux avec un point.
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="2.5" begin="1s" dur="5s" fill="freeze" />
</path>
...
|
Avec ces deux animations, la forme garde ses proportions. Mais vous pouvez aussi la déformer !
Dans ce cas, la valeur de to aura la forme de
facteurDHomothétieX,facteurDHomothétieY. Dans les deux exemples précédents, c'est comme si vous aviez seulement indiqué
facteurDHomothétieX. Le programme prend alors pour acquis que
facteurDHomothétieY est égal à
facteurDHomothétieX.
Voilà pourquoi il était important d'écrire vos nombres à virgule avec un point. Sinon, le programme penserait que vous êtes en train de lui donner un facteurDHomothétieY.
Mais rappelez-vous le cours de maths... l'homothétie se faisait à partir d'un point de référence... Or, on n'a nulle part indiqué ce point...
En effet, le SVG ne gère pas complètement l'animation d'homothéties. Toutes les homothéties sont donc calculées à partir de (0,0). Espérons qu'une prochaine version introduira cette fonctionnalité manquante. (Mais soyons francs, je crois que cela ne vous dérange pas trop, et moi non plus !

)
Dans transform...
Encore une fois, il est possible d'utiliser l'homothétie directement dans la forme. La syntaxe est la même que pour
translate :
Code : XML1
2
3 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" transform="scale(2`1.5)" style="fill:#00DA43; stroke:#28601D;">
...
|
Par contre, cette méthode permet de faire une homothétie à partir d'un autre point que (0,0). L'astuce est de faire subir une translation à la forme, avec comme vecteur le point d'homothétie désiré, effectuer l'homothétie, puis faire la translation inverse. Pour réaliser ceci, nous allons mettre dans transform plusieurs commandes de transformation, espacées par des espaces. (J'ai l'impression de me répéter...

)
Code : XML1
2
3 | ...
<path d="M70`70 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" transform="translate(50`70) scale(3) translate(-50`-70)" style="fill:#00DA43; stroke:#28601D;" />
...
|
Rotation
Poure faire faire une rotation à une forme, c'est
rotate que vous devrez écrire dans
type.
from et
to indiqueront des angles : vous mettrez donc 0 dans from et l'angle de rotation voulu dans to.
Code : XML1
2
3
4
5 | ...
<path d="M150`150 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D;">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="-45" begin="1s" dur="3s" fill="freeze" />
</path>
...
|
Encore une fois, la rotation s'effectue par défaut à partir de (0,0), mais contrairement à l'homothétie, on peut, cette fois, indiquer un point de rotation différent. Nous allons placer une virgule juste après l'angle de rotation, puis indiquer le point de rotation désiré :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D; ">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0`50`50" to="-20`50`50" begin="1s" dur="3s" fill="freeze" />
</path>
...
|
Dans transform...
Encore une fois, on peut utiliser la rotation directement dans
transform :
Code : XML1
2
3 | ...
<path d="M150`150 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" transform="rotate(86`50`70)" style="fill:#00DA43; stroke:#28601D;" />
...
|
Inclinaison
Une inclinaison est un peu plus difficile à expliquer. Et puisqu'une image vaut mieux qu'un long discours...
Inclinaison sur l'axe des x
Un exemple imagé d'inclinaison sur l'axe des x :
->
On voit bien que la forme est inclinée. Cette inclinaison se mesure en degrés, c'est donc des angles que nous mettrons comme valeur de
from et de
to. Vous mettez 0 dans
from et l'angle d'inclinaison dans
to.
L'angle d'inclinaison peut être schématisé comme suit :
Notez que les deux côtés de l'angle
x passent par le milieu des deux formes, perpendiculairement à l'axe des x.
Pour effectuer une inclinaision sur l'axe des x, c'est
skewX qu'il faudra mettre dans l'attribut
type de <animateTransform />.
Pour faire l'inclinaison des images, il faudrait écrire :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; stroke:#28601D; ">
<animateTransform attributeName="transform" attributeType="XML" type="skewX" from="0" to="45" begin="1s" dur="3s" fill="freeze" />
</path>
...
|
Inclinaison sur l'axe des y
Exemple illustré :
->
Le fonctionnement est le même que pour l'inclinaison sur l'axe des x : vous mettez l'angle d'inclinaison dans
to.
Vous remarquerez qu'encore une fois, les deux côtés de l'angle
x passent par le milieu des formes, mais cette fois perpendiculairement à l'axe des y.
Dans l'attribut
type, vous indiquez
skewY :
Code : XML1
2
3
4
5 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" style="fill:#00DA43; fill-opacity:0.5; stroke:#28601D; ">
<animateTransform attributeName="transform" attributeType="XML" type="skewY" from="0" to="45" begin="1s" dur="3s" fill="freeze" />
</path>
...
|
Dans transform...
Pour utiliser l'inclinaison avec l'attribut
transform, c'est l'angle d'inclinaison que nous mettons entre les parenthèses :
Code : XML1
2
3 | ...
<path d="M50`50 q30`50 -10`110 q50`40 100`0 q-40`-60 -10`-110 q-40`-30 -80`0 z" transform="skewX(23)" style="fill:#00DA43;
...
|
Et voilà ! Maintenant, vous pouvez faire de belles animations, et vectorielles en plus

: à bas les gif animés

!