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

DOM

DOM est l’acronyme de Document Object Model. DOM est un ensemble d’interfaces définies par le W3C, le consortium qui se charge de publier les normes du Web. Un parseur DOM prend en entrée un document XML et construit:

  • un arbre formé d’objets chaque objet appartient à une sous-classe de Node
  • des opérations sur ces objets permettent de

créer de nouveaux nœuds, ou de naviguer dans le document

Le DOM représente le document XML en une structure arborescente. Cet arbre contient des nœuds, chaque nœud possède zéro, un ou plusieurs fils. Tout, est un nœud : éléments (on ne dit pas balise mais élément), attributs, commentaires, processing-instructions et texte pour les principaux. Un nœud élément n’est pas le texte qu’il contient. Exemple ci-dessous il y a deux noeuds :

<texte>Le texte</texte>

Les objets de DOM

Les principales classes sont les suivantes :

  • DomNode - objet nœud :

- documents, éléments, nœuds textuels...

  • DomDocument - objet document

- (hérite de DomNode)

  • DomElement - objet élément

- (hérite de DomNode)

  • DomAttr - objet attribut

- (hérite de DomNode)

  • DomNodeList - objet liste de DomNodes

- (ce n'est pas un tableau PHP !)

Les différentes versions

Il existe plusieurs versions du DOM. Toutes sont standardisées par le W3C :

le DOMLevel 1 (Core + HTML) est daté du 1er octobre 1998 ; le DOM Level 2, plus complexe, est divisé en plusieurs parties : Core, Events, Style, Views et Traversal and range, finalisées simultanément le 13 novembre 2000. La spécification DOM Level 2 HTML a été finalisée en janvier 2003 ;
Pour voir le DOM 3 : http://www.w3.org/TR/DOM-Level-3-Core/
Pour le DOM 4 Voir : http://www.w3.org/TR/2012/WD-dom-20121206/#refsDOM3EVENTS

Comprendre un peu mieux la structure avec DOM4 : "les arbres"

Tout comme la plupart des paradigmes de programmation de la plate-forme Web a des arborescences hiérarchiques finies, simplement nommées arbres . L' ordre de l'arbre est précommandé et son parcours se fait en profondeur. Toutes les balises HTML sont donc des nœuds de l'arbre et les feuilles sont soit des balises sans contenu, soit le texte de la page HTML.

  • Un objet qui participe à un arbre a un parent qui est soit un autre objet ou nul, et une liste ordonnée de zéro ou plusieurs enfants objets.
  • La racine d'un objet est lui-même, s'il n'a pas de parent , ou bien elle est la racine de son parent .
  • Un objet A est appelé un descendant d'un objet B , si l' un est un enfant de B ou A est un enfant d'un objet C qui est un descendant de l' hôte .
  • Un descendant inclusive est un objet ou un de ses descendants .
  • Un objet A est appelé un ancêtre d'un objet B si et seulement si B est un descendant d' A .
  • Un ancêtre inclusive est un objet ou un de ses ancêtres .
  • Un objet A est appelé un frère d'un objet B , si et seulement si B et A part le même non nul parent .
  • Un objet A est précédée d'un objet B si A et B sont dans le même arbre et A vient avant B en ordre de l'arbre .
  • Un objet A est suit un objet B si A et B sont dans le même arbre et A vient après B en ordre de l'arbre .
  • Le premier enfant d'un objet est son premier enfant ou nulle si elle n'a pas d' enfant .
  • Le dernier enfant d'un objet est son dernier enfant ou nulle si elle n'a pas d' enfant .
  • Le frère précédent d'un objet est sa première précédente frère ou null si elle n'a pas de précédent fratrie .
  • Le frère suivant d'un objet est son premier suivante frère ou null si elle n'a pas suivant frère .
  • L'index d'un objet est son nombre de précédents frères et sœurs .

Notice: Les fichier sur DOm est à continuer. Ce serait bien de présenter un arbre DOM et l'expliciter

  • Les liens avec Edutehwiki :

http://edutechwiki.unige.ch/fr/Noeuds_:_xml_xhtml_et_DOM http://edutechwiki.unige.ch/fr/Tutoriel_SVG_dynamique_avec_DOM

Avertissement: Validité d'un fichier XHTML

  • XHTML exige que tous les attributs soient écrits en minuscules. Donc, la convention de capitaliser le type d'événement dans un gestionnaire d'événements peur mener à des erreurs de validité en XHTML. (par exemple utilisé "onclick" aulieu de "onClick").
  • Dans un script, certains signes mathématiques peuvent être interprétés comme des caractères spéciaux; (par exemple "i < 5", le < est interprété comme ouverture de balise). Ceci génére par la suite une erreur de validité. Enveloppez votre javascript comme ci-dessous pour le rendre compatible avec xhtml:
<script type="text/javascript">
// <! [CDATA [

// votre code javascript

//]]>
</script>