Le SVG ou « Graphique vectoriel adaptable » utilise le XML non seulement pour stocker ou plutôt générer des formes, des graphiques et des images complexes (Lire à ce sujet « Graphique vectoriel adaptable (SVG) ») il permet aussi de les animer. À l’aide du langage SMIL (Synchronized Multimedia Integration Language) et d’extensions SVG compatible. Et ce sans une seule ligne de Javascript!
Je suis tombé sur le derrière en découvrant la transformation CSS3! Dur coup pour le HTML5, le Javascript et tout particulièrement la librairie jQuery pratiquement indispensable avant son arrivée. Alors imaginez quand j’ai découvert que le SVG permettait lui aussi non seulement le style CSS mais aussi les transitions CSS3. Dans le cas du SVG c’est au tour de la technologie Flash d’en prendre pour son rhume! Bon, Adobe a tout simplement laissé tombé le Flash depuis son rachat. Quand même, le SVG assène à mon avis un coup fatal aux animations Flash paradoxalement incompatible iPad. Comme si Job et Apple avaient profité de l’acquisition de Flash par Adobe pour retirer de la circulation cette technologie! L’AS3 était pourtant tout à fait « scriptural », quoique compilé.
CSS (Cascading Style Sheets)
Le SVG est complètement intégré au DOM (Document object model), on peut donc manipuler le SVG comme tout élément HTML. À l’aide du Javascript mais aussi du CSS et particulièrement de l’animation CSS3. Voir à ce sujet CSS=TRICKS - Animating SVG with CSS. Un exemple avec CSS imbriqué et « mediaquery » :
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 50"> <style> @media all and (max-width: 600px) { #rectangle { transform: rotate(45deg); } } </style> <rect id="rectangle" width="250" height="50" x="0" y="0" fill="#c6c3bd"></rect> </svg>
SMIL (Synchronized Multimedia Integration Language)
Le CSS certes mais surtout le SMIL. Le SMIL permet non seulement d’animer le SVG, il à la particularité d’être carrément imbriqué et associé à l’image et la balise <svg>
! Indépendant du DOM (document object model) il affecte l’image peut importe son contexte et offre plus de fonctionnalités.
Enfin, toujours est-il que le langage SMIL est largement supporté aujourd’hui par la majorité des navigateurs. À part toutes les versions d’Internet Explorer! En général j’excuse les abus de Microsoft par son culot, son développement. Mais dans le cas du SMIL, Microsoft a tout simplement passé à côté! Ceci dit, l’animation SVG fonctionne très bien avec les versions tant de bureau que mobiles des navigateurs Firefox, Safari et Google Chrome! Voir la Table de compatibilité des animations SVG SMIL. Ce qui en fait la meilleurs solution, la plus portable et surtout la solution d’avenir!
Pure SMIL
Il y a déjà le SMIL pour transformer un vecteur SVG.
- <animate>
- permet aux attributs et aux propriétés scalaires de recevoir différentes valeurs dans le temps.
- <set>
- un raccourci pratique pour l’élément ’animate’, utile lors de l’assignation de valeurs d’animation à des attributs et propriétés non numériques, telle que la propriété
visibility
. - <animateMotion>
- déplace un élément le long d’un tracé de mouvement.
- <animateColor>
- modifie la valeur de couleur des attributs et des propriétés particuliers au cours du temps.
Exemple simple inspiré par CSS-TRICS avec l’élément <animate>
<svg width="100%" height="50"> <rect id="rectangle" width="50" height="50" x="0" y="0" fill="#c6c3bd"></rect> <animate xlink:href="#rectangle" attributeName="x" from="0" to="100%" dur="5s" begin="0s" repeatCount="indefinite" fill="freeze" id="rect-anim"/> </svg>
L’horloge SVG
Nous verrons donc dans ce tutoriel l’animation, essentiellement la rotation. Commençons par « définir » l’image SVG et les trois aiguilles en leur attribuant chacune un « id » pour les réutiliser plus tard. Ensuite le graphique de l’horloge, c’est-à-dire un simple cercle et douze petites lignes :
- Définition des trois lignes pour les aiguilles (avec ID)
- Un cercle et ses douze petites lignes
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" > <defs> <line x1="100" y1="100" x2="100" y2="45" style="stroke-width: 6px; stroke: black;" id="oHeure"/> <line x1="100" y1="100" x2="100" y2="15" style="stroke-width: 4px; stroke: black;" id="oMinute"/> <line x1="100" y1="100" x2="100" y2="5" style="stroke-width: 2px; stroke: red;" id="oSeconde"/> </defs> <g> <circle id="circle" style="stroke: black; fill: #d6d3ce;" cx="100" cy="100" r="100"/> <line style="stroke: black;" id="hour0" x1="100" y1="10" x2="100" y2="0"/> <line style="stroke: black;" id="heure1" x1="150" y1="13" x2="145" y2="22"/> <line style="stroke: black;" id="heure2" x1="187" y1="50" x2="178" y2="55"/> <line style="stroke: black;" id="heure3" x1="190" y1="100" x2="200" y2="100"/> <line style="stroke: black;" id="heure4" x1="187" y1="150" x2="178" y2="145"/> <line style="stroke: black;" id="heure5" x1="150" y1="187" x2="145" y2="178"/> <line style="stroke: black;" id="heure6" x1="100" y1="190" x2="100" y2="200"/> <line style="stroke: black;" id="heure7" x1="50" y1="187" x2="55" y2="178"/> <line style="stroke: black;" id="heure8" x1="13" y1="150" x2="22" y2="145"/> <line style="stroke: black;" id="heure9" x1="0" y1="100" x2="10" y2="100"/> <line style="stroke: black;" id="heure10" x1="13" y1="50" x2="22" y2="55" /> <line style="stroke: black;" id="heure11" x1="50" y1="13" x2="55" y2="22" /> </g> </svg>
Résultat
Animer les aiguilles en SVG
Les attributs de transformation SVG sont en fait des extensions et des valeurs destinées aux attributs SMIL (SMIL Animation compatibles), notamment animateMotion
. Un tracé de mouvement (path) que parcourt l’animation. Voilà les éléments et attributs :
- <animateTransform>
- comme l’attribut
transform
permet de modifier les attributs de transformation SVG dans le temps. - path (attribut)
- utilisé en combinant l’attribut SMIL <animateMotion>. Permet de spécifier les coordonnées d’un tracé de mouvement.
- L’élément <mpath>
- permet à un élément <animateMotion> de contenir un élément enfant <mpath>, qui appelle un élément SVG <path> comme définition du tracé de mouvement.
- keyPoints (attribut)
- ajoute un attribut keyPoints à l’élément <animateMotion> pour offrir un contrôle précis des animations d’un tracé de mouvement.
- rotate (attribut)
- ajoute un attribut « rotate » à l’élément <animateMotion> pour le contrôle automatique de la rotation d’un objet, de façon à ce que son axe-x se dirige dans la même direction (ou dans la direction opposée) que le vecteur tangent directionnel du tracé de mouvement.
Le secret est d’utiliser la balise defs
pour définir au préalable les éléments à animer (les aiguilles) qui seront par la suite récupéré par la balise use
et la référence : xlink:href=[référence]
. La transformation applique une simple rotation de 360 degrés sur l’axe du milieu. L’important ici c’est la duré de la rotation :
- 43200 secondes pour les heures
- 3600 secondes pour les minutes
- 60 secondes pour les secondes
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <title>Horloge analogique SVG</title> <desc>Affiche l’heure en Temps universel coordonné (UTC).</desc> <defs> <line id="oHeure" x1="100" y1="100" x2="100" y2="45" style="stroke-width: 6px; stroke: black;"/> <line id="oMinute" x1="100" y1="100" x2="100" y2="15" style="stroke-width: 4px; stroke: black;"/> <line id="oSeconde" x1="100" y1="100" x2="100" y2="5" style="stroke-width: 2px; stroke: red;"/> </defs> <g> <circle id="circle" style="stroke: black; fill: #d6d3ce;" cx="100" cy="100" r="100"/> <line style="stroke: black;" id="hour0" x1="100" y1="10" x2="100" y2="0"/> <line style="stroke: black;" id="hour1" x1="150" y1="13" x2="145" y2="22"/> <line style="stroke: black;" id="hour2" x1="187" y1="50" x2="178" y2="55"/> <line style="stroke: black;" id="hour3" x1="190" y1="100" x2="200" y2="100"/> <line style="stroke: black;" id="hour4" x1="187" y1="150" x2="178" y2="145"/> <line style="stroke: black;" id="hour5" x1="150" y1="187" x2="145" y2="178"/> <line style="stroke: black;" id="hour6" x1="100" y1="190" x2="100" y2="200"/> <line style="stroke: black;" id="hour7" x1="50" y1="187" x2="55" y2="178"/> <line style="stroke: black;" id="hour8" x1="13" y1="150" x2="22" y2="145"/> <line style="stroke: black;" id="hour9" x1="0" y1="100" x2="10" y2="100"/> <line style="stroke: black;" id="hour10" x1="13" y1="50" x2="22" y2="55" /> <line style="stroke: black;" id="hour11" x1="50" y1="13" x2="55" y2="22" /> </g> <g> <use xlink:href="#oHeure"> <animateTransform attributeName="transform" type="rotate" dur="43200s" values="0, 100, 100; 360, 100, 100" repeatCount="indefinite" /> </use> </g> <g> <use xlink:href="#oMinute"> <animateTransform attributeName="transform" type="rotate" dur="3600s" values="0, 100, 100; 360, 100, 100" repeatCount="indefinite" /> </use> </g> <g> <use xlink:href="#oSeconde"> <animateTransform attributeName="transform" type="rotate" dur="60s" values="0, 100, 100; 360, 100, 100" repeatCount="indefinite" /> </use> </g> </svg>
Résultat :
Javascript
À ce stade ci, l’horloge est complète et animée sans une seule ligne de Javascript! Ce qui n’empêche pas d’utiliser un langage script pour manipuler directement le nouvel objet. Car contrairement au Flash, une animation SVG est entièrement intégrée au DOM. Par exemple donner la bonne heure à notre horloge. D’ailleurs le Javascript s’imbrique à l’intérieur de la définition de la balise svg
.
<svg onload="twAjusteHeure(evt)"... <defs> <line id="oHeure" x1="100" y1="100" x2="100" y2="45" style="stroke-width: 6px; stroke: black;"/> <line id="oMinute" x1="100" y1="100" x2="100" y2="15" style="stroke-width: 4px; stroke: black;"/> <line id="oSeconde" x1="100" y1="100" x2="100" y2="5" style="stroke-width: 2px; stroke: red;"/> <script type="text/javascript"> <![CDATA[ function twAjusteHeure(e) { var d = new Date(); var s = d.getSeconds(); var m = d.getMinutes() + s / 60; var h = d.getHours() + m / 60; var svg = e.target.ownerDocument; svg.getElementById("oSeconde").setAttribute("transform", "rotate(" + (s * 6) + ", 100, 100)"); svg.getElementById("oMinute").setAttribute("transform", "rotate(" + (m * 6) + ", 100, 100)"); svg.getElementById("oHeure").setAttribute("transform", "rotate(" + (h * 30) + ", 100, 100)"); } //]]> </script> </defs> [...] </svg>
Internet Explorer / Javascript
L’animation n’est malheureusement pas compatible Internet Explorer (Internet Explorer Dev Center - Basic SVG animation). Pour Internet Explorer il faut absolument utiliser le Javascript. David Basoko a produit un bon exemple entièrement Javascript et compatible Internet Explorer : SVG clock animation.
Références
- Yoyodesign 19 L’animation - SVG 1.0
- CSS-TRICKS - A Guide to SVG Animations (SMIL)
- Wikipedia - File:Animated analog SVG clock.svg
- Adobe Developer Connection / SVG Developer Center
- W3C Recommendation - SMIL Animation
- Javascript, SVG and DOM
- Animated Clocks for SVG and Silverlight
- Graphique vectoriel adaptable (SVG)
- SVG Tutorial par Jakob Jenkov
- Internet Explorer Dev Center - Basic SVG animation