Tutoriel SVG/SMIL animations interactives

De EduTech Wiki
Aller à la navigation Aller à la recherche

<pageby nominor="false" comments="false"/>

Cet article est une ébauche à compléter. Une ébauche est une entrée ayant un contenu (très) maigre et qui a donc besoin d'un auteur.

Interactivité avec SVG

Principe et gestion des événements

L’interactivité et donc la gestion des événements ressemble au principe des GUI modernes (par exemple en JavaScript ou ActionScript) et elle est conforme à la spécification DOM2.

Types d’interactivité:

  • Des actions initiées par l'utilisateur, telle que presser le bouton d'une souris, peuvent causer l'exécution d'animations ou de scripts;
  • L'utilisateur peut initier des hyperliens vers de nouvelles pages Web par des actions (par ex. cliquer sur un élément)
  • L'utilisateur peut zoomer dans un contenu SVG ou effectuer un panoramique autour de celui-ci (dépend du client).
  • Les déplacements par l'utilisateur du dispositif de pointage peuvent modifier le curseur qui indique sa position

L’essentiel, SVG comprend

  • des attributs d'événements (ex. onclick="hello()" ) pour lancer des scripts
  • des noms d’ événements qu’on peut insérer dans certains attributs (par ex: begin="click" ) et qui définissent l’élément d’animation à déclencher quand un événement donné survient.

Evénements SVG/SMIL

La spécification SVG1 définit plus de 20 événements. Les plus importants peuvent être capturés par des "attributs d’événements" qu’on insère dans les balises qu’on veut rendre interactives.

Il existe certains événements sans attributs qui concernent la modification de l’arbre DOM. En plus, à l'aide du Modèle Objet de Document (DOM) de SVG, un script peut enregistrer des guetteurs d'événements (event handlers) DOM2 de manière à ce qu'un script puisse être invoqué quand un événement donné survient.

Un résumé des noms et attributs d’événement

Le nom de l’événement sera utilisé pour identifier un event dans des balises d’animation (comme "begin").

 <animateColor fill="freeze" dur="0.1s" to="blue" from="yellow"
               attributeName="fill" begin="mouseover"/>

L’attribut d’événement permet de placer des "guetteurs d’événement"

<circle onmouseover="circle_click(evt)" cx="300" cy="225" r="100" fill="red"/>

Donc attention : Ne confondez pas nom d’événement à utiliser dans les attributs des éléments d’animation et attributs d’événements pour lancer des scripts !!

"mouseover" pas égal à "onmouseover" (.... ou vous perdrez qq. heures ...)

La table suivante réunit la définition de quelques éléments et attributs associés

Nom de
l'événement

Description: un événement survient quand ...

Attribut
d'événement

focusin

un élément reçoit l'attention (le focus), par ex. l’élément 'text' devient sélectionné.

onfocusin

focusout

un élément perd l'attention, (désélection).

onfocusout

activate

un élément est activé, par exemple, au travers d'un clic de souris ou l'appui d'une touche.

  • Un argument numérique est fourni pour indiquer le type d'activation :
    1 pour une activation simple (par ex. simple clic ou la touche Entrée),
    2 pour une hyperactivation (par ex. un double-clic ou la combinaison de touches).

onactivate

click

le bouton du dispositif de pointage (souris, touchpad, stylo etc.) est cliqué au-dessus d'un élément.

  • Un clic est l'appui et le relâchement du bouton de la souris au-dessus d'une même position sur l'écran. (mousedown/mouseup sont avant/après).

onclick

mousedown

le bouton de pointage est pressé au-dessus d'un élément.

onmousedown

mouseup

le bouton de pointage est relâché au-dessus d'un élément.

onmouseup

mouseover

le dispositif de pointage est déplacé sur un élément.

onmouseover

mousemove

le dispositif de pointage est déplacé alors qu'il est au-dessus d'un élément..

onmousemove

mouseout

le dispositif de pointage (souris) est écarté de l’élément.

onmouseout

SVGLoad

le client a complètement interprété l'élément et ses descendants

  • il est prêt à agir de manière appropriée sur cet élément (affichage par exemple). Les ressources externes appelées requises doivent être chargées, interprétées et prêtes aussi.

onload

SVGUnload

le client enlève le document SVG (élément svg le plus externe)

onunload

SVGAbort

le chargement de la page est interrompu avant qu'un élément ait pu être complètement chargé.

onabort

SVGError

un élément ne se charge pas correctement ou quand une erreur survient lors de l'exécution d'un script.

onerror

SVGResize

une vue de document (svg le plus externe) est redimensionnée.

onresize

SVGScroll

une vue du document est glissée sur X, sur Y ou les deux.

onscroll

SVGZoom

le document change de niveau de zoom lors d'une interaction avec l'utilisateur. (éléments 'svg' les plus externes).

onzoom

beginEvent

un élément d'animation commence.

  • voir la description de l'interface TimeEvent dans la spéci.SMIL

onbegin

endEvent

un élément d'animation s'achève (voir TimeEvent)

onend

repeatEvent

un élément d'animation se répète.

  • Il est déclenché toutes les fois où l'élément se répète, après la première itération. (voir l'interface TimeEvent aussi)

onrepeat

Exemple Simple animation avec un événement mouseover

On va d'abord examiner quelques fragments du code avant de montrer le tout.

(1) Un lien vers un autre URL se met simplement autour de l'élément cliquable

  <a xlink:href="http://tecfa.unige.ch">
   <rect style="fill:#00FF00;stroke:#00FF00" width="200"
          height="26" ry="5" rx="5" y="100" x="100"/>
  </a>

(2) L’ellipse jaune qui contient un texte va activer une animation (changement de couleur) lorsqu’on glisse la souris dessus ou lorsqu’on la sort de nouveau (l’attribut "begin" va s’activer lorsqu’il y a un mouseover ou un mouseout).

<g transform="translate(100,100)">
    <ellipse stroke-width="2" stroke="black" fill="yellow" ry="1cm" rx="2cm"
             id="hint_button">
      <animateColor fill="freeze" dur="0.1s" to="blue" from="yellow"
                    attributeName="fill" begin="mouseover"/>
      <animateColor fill="freeze" dur="0.1s" to="yellow" from="blue"
                    attributeName="fill" begin="mouseout"/>
    </ellipse>
    <text style="font-size:12;" alignment-baseline="middle" x="-1cm">Touch me !</text>
</g>

(3) Ensuite, on a un contenu caché et qui s’affiche lorsque l'élément qui a l'id "hint_button " rencontre un évément mouseover. Autrement dit: l'attribut "begin" d'une animation ne peut pas seulement être un temps, un événement de l'élément parent comme ci-dessus, mais également un événement qui a lieu dans un autre élément (l'ellipse dans notre cas anime la propriété style du cercle caché)!!

<g transform="translate(100,200)" style="display:none">
 <circle style="fill:yellow;" r="2cm" cy="1cm" cx="1cm"/>
    <text style="font-size:12;" alignment-baseline="middle" x="-0.8cm" y="1cm">
    Find the scecret URL !</text>

    <animate fill="freeze" dur="0.1s" begin="hint_button.mouseover"
      from="none" to="block" attributeName="display"/>
    <animate fill="freeze" dur="0.1s" begin="hint_button.mouseout"
      from="block" to="none" attributeName="display"/>
</g>

Voici l'exemple complet:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" 
  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg height="900" width="900" 
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns="http://www.w3.org/2000/svg">
  
  <desc>Un lien se me simplement autour de l'élément qui fait
  "hint_button"</desc>

  <a xlink:href="http://tecfa.unige.ch">
   <rect style="fill:#00FF00;stroke:#00FF00" width="200" 
         height="26" ry="5" rx="5" y="100" x="100"/>
  </a>

  <desc>Ici on implémente un hint_button avec une ellipse qui contient
  un texte. Les éléments d'animation sont placés à l'intérieur d'une
  éllipse. L'animation (un changement de couleur) va s'activer
  lorsqu'il y a un mouseover (l'attribut "begin" va s'activer). Note:
  un événement mouseover aura un deuxième effet. L'identificateur
  "hint_button" se retrouve dans les éléments d'animations ci-après
  (le circle) et va aussi déclencher une action</desc>

  <desc>This bouton will change color when mouseover, back to original
  when the mouse moves out. Notice the hint_button id which we will
  use later.</desc>

  <g transform="translate(100,100)">
    <ellipse stroke-width="2" stroke="black" fill="yellow" 
             ry="1cm" rx="2cm" id="hint_button">
      <animateColor fill="freeze" dur="0.1s" to="blue" from="yellow" 
                    attributeName="fill" begin="mouseover"/>
      <animateColor fill="freeze" dur="0.1s" to="yellow" from="blue" 
                    attributeName="fill" begin="mouseout"/>
    </ellipse>
    <text style="font-size:12;" alignment-baseline="middle" x="-1cm">Touch me !</text>
  </g>

  <desc>Ici on a un contenu caché et qui se déclenche (affiche)
  lorsque l'élément qui a l'id "hint_button" a un mouseover. Autrement
  dit: l'attribut "begin" d'une animation ne peut pas seulement être
  un temps, un événement de l'élément parent comme ci-dessus, mais
  également un événement qui a lieu dans un autre élément (l'ellipse
  dans notre cas)!!  </desc> <desc> This is a hidden content that will
  appear on mouseover of the element that has id=hint_button that we
  defined above.</desc>

  <g transform="translate(100,200)" style="display:none">
    <circle style="fill:yellow;" r="2cm" cy="1cm" cx="1cm"/>
    <text style="font-size:12;" alignment-baseline="middle" x="-0.8cm" y="1cm">
    Find the scecret URL !</text>

    <animate fill="freeze" dur="0.1s" begin="hint_button.mouseover"
      from="none" to="block" attributeName="display"/>
    <animate fill="freeze" dur="0.1s" begin="hint_button.mouseout"
      from="block" to="none" attributeName="display"/>
  </g>
</svg>

Résumé

  • Des animations peuvent se déclencher suite à un geste d’utilisateur.
  • Le geste de l’utilisateur crée un événement géré (ici) par les balises "begin".
  • Autrement dit, le "begin" fait guetteur d’événement pour l’événement nommé.
  • Une animation d’un élément peut se déclencher suite à un événement qui a lieu dans un autre élément (on bouge la souris sur l’ellipse et c’est le cercle qui apparaît)

Interaction SMIL - script

Il existe deux cas de figure:

  • Script -> SMIL
  • SMIL -> Script

Ci-dessous un simple exemple qui montre comment déclencher un script depuis SVG et ensuite le script qui arrête l'animation avec une simples méthode DOM.

Exemple Pendule

<?xml version="1.0" ?>

<svg xmlns="http://www.w3.org/2000/svg" version="1.0" 
     viewBox="0 0 300 200">
<script>
  function stop () {
   document.documentElement.pauseAnimations();
  }

  function start () {
   document.documentElement.unpauseAnimations();
  }

</script>
<desc>
  The pendulum code was taken from http://www.treebuilder.de/xul/svg2apng/pendel.svg. The pauseAnimations method is documented in the SVG 1.1 spec: http://www.w3.org/TR/SVG/struct.html#__svg__SVGSVGElement__pauseAnimations
 </desc>
<g>
<line x1="100" y1="0" x2="100" y2="90" stroke="black"/>
<circle cx="100" cy="90" r="10"/>
<animateTransform attributeName="transform" type="rotate" values="0,100,0;70,100,0;0,100,0;-70,100,0;0,100,0" keySplines="0,0.5,0.5,1;0.5,0,1,0.5;0,0.5,0.5,1;0.5,0,1,0.5" calcMode="spline" begin="0s" dur="4s" repeatCount="indefinite"/>
</g>

<g onclick="stop()" transform="translate(150 0)">
<rect width="50" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
<text id="t" style="font:16px Arial Black;fill:white;stroke:black" transform="translate(5 20)">STOP</text>
</g>

<g onclick="start()" transform="translate(5 0)">
<rect width="50" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
<text id="t" style="font:16px Arial Black;fill:white;stroke:black" transform="translate(2 20)">START</text>
</g>


</svg>

Exemple du pendule détail

L'attibut viewBox indique la grandeur et la hauteur de votre animation

viewBox="0 0 300 200" 

Le code JavaScript définit ce que les boutons "stop et Start" vont faire. L'animation (le pendule) va stopper quand on appuie sur le bouton gris "stop" et recommencer quand on appuie sur le bouton "start"

<script>
  function stop () {
   document.documentElement.pauseAnimations();
  }

  function start () {
   document.documentElement.unpauseAnimations();
  }

</script>

Après la définition des fonctions JavaScript dans l'élément </script>, on commence à faire la mise en forme du pendule mais aussi des boutons "stop et start"

Commençons par la ligne le cerle et le mouvement de balancier :

<line x1="100" y1="0" x2="100" y2="90" stroke="black"/><br />
  • Cela dit :

que l'on a construit une ligne noire ( stroke) avec certaine mesure : x1="100" y1="0" x2="100" y2="90".
Pour rappel :

  • x1 : spécifie la position du premier point sur l'axe des abscisses ;
  • x2 : spécifie la position du second point sur l'axe des abscisses ;
  • y1 : spécifie la position du premier sur l'axe des ordonnées ;
  • y2 : spécifie la position du second point sur l'axe des ordonnées ;
<circle cx="100" cy="90" r="10"/><br />

Cela dit que l'on a construit un cercle avec certaine mesure : cx="100" cy="90" r="10"
Pour rappel :

  • L'attribut r spécifie le rayon du cercle, et les attributs cx et cy les coordonnées du centre.
  • Maintenant il s'agit d'animer le pendule :
<animateTransform attributeName="transform" type="rotate" 
      values="0,100,0;70,100,0;0,100,0;-70,100,0;0,100,0" 
      keySplines="0,0.5,0.5,1;0.5,0,1,0.5;0,0.5,0.5,1;0.5,0,1,0.5" 
      calcMode="spline" begin="0s" dur="4s" repeatCount="indefinite"/><br />
  • La première partie dit que c'est : un élément qui va bouger et cela donne les valeurs, le type et le mode ce calcul.
  • La deuxième partie va dire :

Que l'élément qui va bouger :

  • Va commencer à : "o" :begin="0s"
  • qu'il va durer 4 seconde : dur="4s"
  • qu'il va toujours se répéter : "indefinite"

Maintenant tout est dit pour le pendule et on ferme la balise </g>.
On va s’intéresser au bouton start et stop.

Nous allons détaillé le bouton "stop" car l'autre ( start) est basé le même principe ( on a ouvert de nouvelle balise <g>).

<g>
<g onclick="stop()" transform="translate(150 0)">
<rect width="50" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
<text id="t" style="font:16px Arial Black;fill:white;stroke:black" transform="translate(5 20)">STOP</text>
</g>

<g onclick="stop()" transform="translate(150 0)">

  • On réfère ici à la function que l'on a défini plus en amont dans la page:
 function stop () {
   document.documentElement.pauseAnimations();

On dit juste que ce bouton devra "fonctionner" avec onclick. C'est-à-dire : arrêter le mouvement du pendulier( vous pouvez aller voir les possibilités en amont dans le tableau). On aurait pu aussi le faire en faisant passer la souris juste dessus les boutons pour stopper le mouvement).

  • Ensuite : il faut dire où l'on veut dans l'espace le bouton avec : transform="translate(150 0)"
  • On donne la forme et l'opacité au rectangle  : <rect width="50" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
  • Maintenant on utilise le <text..</text> et on lui donne son style. Cela correspond au "stop" écrit dans le bouton gris.

On fait de même avec le bouton "start" et on referme la balise </g>, ainsi que la balise finale : </svg>

  • Et voilà, vous n'avez plus qu'à aller à nouveau observer le modèle en fonction.

http://tecfa.unige.ch/guides/svg/ex/smil-dom/pendula.svg