Tutoriel SVG/SMIL animations interactives

De EduTech Wiki
Aller à la navigation Aller à la recherche
La version imprimable n’est plus prise en charge et peut comporter des erreurs de génération. Veuillez mettre à jour les signets de votre navigateur et utiliser à la place la fonction d’impression par défaut de celui-ci.

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

Prérequis:

Principe et gestion des événements

L’interactivité est donc la gestion des événements qui ressemblent au principe des GUI (aussi nommée interface graphique) modernes (par exemple en JavaScript ou ActionScript) et elle est conforme à la spécification DOM2 (document object model).

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

Exemples

Simples mouse click et mouse over

L'animation de type SVG-SMIL permet d'utiliser les événements de façon très simple Quelque chose comme Button.click permet de se référer au click sur un élément qui a un id=Button et de lancer une animation

Voici une illustration:

 <svg style="margin-left:50px;border:1px solid blue" height="300" width="300" 
	 xmlns:xlink="http://www.w3.org/1999/xlink"
	 xmlns="http://www.w3.org/2000/svg">
  
      <g id="Button"
	 transform="translate(100,100)">
	<ellipse stroke-width="2" stroke="none" fill="yellow" ry="1cm" rx="2cm" >
	  <animate fill="freeze" dur="1s" begin="Button.click" from="1cm" to="5cm" attributeName="ry"/>
	  <animate fill="freeze" dur="1s" begin="Button.click" from="2cm" to="10cm" attributeName="rx"/>
	</ellipse>
	<text style="font-family:Arial;font-size:18;" alignment-baseline="middle" x="-1cm">Click me !</text>
      </g>      
    </svg>

Code source (avec variantes)

Lancer une animation de mouvement:

Cet exemple montrent comment inclure un dessin compliqué avec un élément svg qui remet les coordonnées de l'objet à animer à 0/0. Si vous ne faites pas cela, vous allez en baver avec un dessin compliqué ...

Example Mouse over/out

<?xml version="1.0" ?>
<svg height="200" width="500" 
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns="http://www.w3.org/2000/svg">
  
  <ellipse stroke-width="2" stroke="black" fill="yellow" 
	   cx="3cm" cy="2cm" ry="1cm" rx="2cm">
    <animate fill="freeze" dur="0.1s" to="blue" from="yellow" 
		  attributeName="fill" begin="mouseover"/>
    <animate fill="freeze" dur="0.1s" to="yellow" from="blue"
		  attributeName="fill" begin="mouseout"/>
  </ellipse>
</svg>

Live example / source code:

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>

Interaction mouse click et animation invisible/visible

L'objectif ici est de créer une page HTML5 avec un contenu, où lorsque l’utilisateur clique sur un bouton, cela fait apparaître un objet.

Créer une forme qui sera la base d'un bouton. Le nom du dessin est donné automatiquement (svg_1), pour plus de facilité par la suite et pour pouvoir se retrouver dans le code, je le renomme btn_ovale.

Ex11 1.jpg


  • Créer le texte du bouton. Nommé automatiquement svg_2, je le renomme btn_txt
Ex11 2.jpg


  • Grouper les deux éléments pour en construire un seul. Je le renomme "bouton".
Ex11 3.jpg


  • Créer un élément qui va apparaître lorsqu'on clique sur le bouton. J'ai créé un rectangle composé de 2 rectangles groupés et je l'ai nommé "rectangles".
Ex11 4.jpg


  • Cliquer sur l'icône svg, cela donne le code des dessins réalisés.
Ex11 5.jpg


  • Créer une page HTML5. Pour ce faire, je me suis basée sur le code suivant, trouvé ici
<!DOCTYPE html>
<html>
  <head>
    <title>HTML5 SVG demo</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  </head>

  <body>
    <h1>HTML5 SVG Demo</h1>

A nice green circle:
    <svg id="circle" height="200" xmlns="http://www.w3.org/2000/svg">
      <circle id="greencircle" cx="30" cy="30" r="30" fill="green" />
    </svg>

    <hr>
    <address>Created by DKS. This is free code</address>
</html>

Une fois le code collé dans l'éditeur de code source, enregistrer le fichier en format html.


  • Copier-coller le code généré par le svg-editor à l'endroit indiqué
Ex11 6.jpg


  • Ajouter le code pour l'interaction/animation aux endroits indiqués
Ex11 7.2.jpg


  • Si vous testez le fichier dans un validateur htlm, vous verrez des erreurs du type : "Bad value null for attribute stroke-linejoin on element rect." Il suffit de supprimer les attributs stroke-linejoin et stroke-linecap et les valeurs "null" indiquées par le validateur html. En effet, il semblerait que les attributs stroke-linejoin et stroke-linecap n'acceptent pas la valeur "null".



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>

Alternative sans script:

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 cercle 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