Tutoriel SVG dynamique avec DOM
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.
<pageby nominor="false" comments="false"/>
Avertissement: Il faudrait complètement revoir ce texte. Il a été écrit il y a longtemps quand les navigateurs implémentaient mal SVG - Daniel K. Schneider 26 mars 2011 à 15:55 (CET)
Consultez plutôt:
- http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html (enfin même ce document semi-officiel n'est pas à jour pour HTML5)
Introduction
Créer des interactions et animations avec le DOM est plus difficile que SVG dynamique avec SMIL, mais on peut faire ce qu’on veut selon le principe que tous les attributs du DOM sont animables.
Certains types d’interactions peuvent se programmer sans savoir grand chose de la programmation DOM (c’est pareil pour le traitement de formulaires HTML avec Javascript ...)
Etat de la technologie début 2011. SVG stand-alone ou SVG dans XHTML:
- marche avec Firefox, Opéra, Chrome, Safari (?)
- marchera avec IE9 Béta (?)
Pour HTML 5, consultez Inline SVG in HTML5.
- Chrome 10 ou 11 semblent le mieux marcher
Voici le principe:
- Dans l’élément qui doit déclencher un script on place un attribut d’événement, par exemple onclick (Voir tutoriel SVG dynamique avec SMIL)
- Cet attribut doit définir un fonction avec un argument
- le nom d’une fonction ECMAScript, par ex: circle_click et qui sera appelée
- un argument avec lequel sera transmis un objet événement, par ex. evt
Un objet événement est dynamiquement crée par le client. Il contient des informations variées, par exemple où l’événement a été déclenché etc.
function circle_click(evt) {
var circle = evt.target;
var currentRadius = circle.getAttribute("r");
}
<circle onclick="circle_click(evt)" cx="300" cy="225" r="100" fill="red"/>
Exemple : Simple switch avec DOM
- http://www.yoyodesign.org/doc/w3c/svg1/animate.html (original, home de la traduction française de la spécification SVG 1.0)
- http://tecfa.unige.ch/guides/svg/ex/svg-w3c/script01.svg
- http://tecfa.unige.ch/guides/svg/ex/svg-w3c/
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="6cm" height="5cm" viewBox="0 0 600 500"
xmlns="http://www.w3.org/2000/svg">
<desc>Exemple script01 - invoque une fonction ECMAScript
a partir d'un evenement onclick </desc>
<!-- Fonction ECMAScript qui change le rayon a chaque clic -->
<script type="text/ecmascript"> <![CDATA[
function circle_click(evt) {
var circle = evt.target;
var currentRadius = circle.getAttribute("r");
if (currentRadius == 100)
circle.setAttribute("r", currentRadius*2);
else
circle.setAttribute("r", currentRadius*0.5);
}
]]> </script>
<!-- Contour en bleu de l'aire du dessin -->
<rect x="1" y="1" width="598" height="498" fill="none" stroke="blue"/>
<!-- S'execute a chaque clic -->
<circle onclick="circle_click(evt)" cx="300" cy="225" r="100"
fill="red"/>
<text x="300" y="480"
font-family="Verdana" font-size="32" text-anchor="middle">
Cliquer sur le cercle change sa taille
</text>
</svg>
Explications:
- L’exemple implémente un switch (assimilable à un interrupteur de lumière)
- On ajoute à la définition cercle un event-handler. Autrement dit: en cliquant sur le cercle (événement = "onclick"), la fonction circle_click ("event handler") va être activée avec l'argument "evt"
<circle onclick="circle_click(evt) cx="300" cy="225" r="100" fill="red"/>
- La fonction circle_click qu’on a défini va recevoir comme argument un objet événement ( le paramètre evt )
- L’objet evt sait quel objet a été touché par l’événement. Autrement dit, evt.target contient l’objet DOM du cercle et on l’assigne à la variable circle .
function circle_click(evt) {
var circle = evt.target;
.....
}
- Ensuite on demande au cercle son attribut "r" (qui définit le radius)
var currentRadius = circle.''getAttribute("r");
Le code suivant substitue la valeur du "r":
- si le radius == 100, alors on va l’agrandir
- sinon, on va le diminuer
if (currentRadius == 100)
circle.setAttribute("r", currentRadius*2);
else circle.setAttribute("r", currentRadius*0.5);
facile, non ? (ce genre de choses se fait aussi en X3D, en HTML et en VRML)
Introduction au scripting avec DOM
Placement et initialisation du script
Le script doit se trouver dans une section CDATA du code SVG, comme en XHTML. La raison est simple: pour que le XML soit bien formée, on peut ne peut pas y inclure des éléments utilisant une autre syntaxe.
<script type="text/ecmascript">
<![CDATA[
function circle_click(evt) {
..... }
]]>
</script>
Un script travaille souvent avec des variables globales et il faut faire de sorte à ce que l’initialisation soit déjà faite lorsque l’utilisateur interagit avec la scène.
Voici une façon de faire:
<svg
<script type="text/ecmascript"> <![CDATA[
// variables globales qu'on utilise dans toutes les fonctions
var svgdoc, eye_right, ...... ;
function init (big_bang) {
svgdoc = big_bang.target.ownerDocument; // instance of the document
..... }
<svg onload="init(evt)">
<desc> Ici on insère la véritable scène SVG </desc>
</svg>
</svg>
L’élément svg imbriqué déclenche le script init() lorsqu’il est chargé
Une autre façon est la suivante:
<svg width="4cm" height="2cm" viewBox="0 0 400 200"
xmlns="http://www.w3.org/2000/svg"
onload="DebuterAnimation(evt)" >
<script type="text/ecmascript"><![CDATA[
function DebuterAnimation(evt) {
racine = evt.target.ownerDocument;
}
function XXX {
}
</script>
<rect .... />
</svg>
Le déboggage
Si vous le souhaitez vous pouvez utiliser des outils comme [FireBug] pour débugger votre script. Sinon quelques autres solutions sont présentées ci-dessous.
Une solution est de semer partout dans votre code des "alert" qui produisent des fenêtres pop-up lorsque la ligne est exécutée.
Au lieu de les copier/coller tout le temps on propose la solution suivante:
- Une variable globale debug qu’on peut mettre à 0, 1 ou 2 selon vos besoin.
- Si par exemple un problème est résolu, on met le "debug level" à 2. Si debug==1 on ne voit plus l’alert.
// set to 0 in production, 1 for things to debug, 2 for things fixed
var debug = 1;
Voici une du code pour produire les "alert"
if (debug==2) alert ("The document did load nicely, global variables are defined");
// affiche un string plus une représentation d’un objet
if (debug==1) alert ("button =" + currentButton);
... sans ce genre de stratégie vous allez souffrir, car il est facile de mal interpréter les spécifications du DOM ....
Classes et méthodes SVG DOM et XML DOM 2
Une liste complète des classes et méthodes SVG DOM serait monstrueuse, il existe une vingtaine de "chapitres" avec nombreuses classes et méthodes.
Tout SVG est répliqué dans DOM (donc y compris animations et interactivité)
A titre d’exemple, il y a 13 classes DOM spécifiques à la structure du document SVG: SVGDocument, SVGSVGElement, SVGGElement, SVGDefsElement, SVGDescElement, SVGTitleElement, SVGSymbolElement, SVGUseElement, ....
Sinon, SVG implémente DOM2 et nous allons surtout utiliser cela par la suite
L’interface SVGDocument
Un objet de type SVGDocument va exister quand l'élément racine de la hiérarchie du document XML est un élément 'svg' (cela correspond à HTMLDocument) On peut utiliser cet interface pour chercher des éléments par leur id par exemple.
svgdoc = big_bang.target.ownerDocument; // instance of the document
eye_right = svgdoc.getElementById ("eyeRightId"); // getElementById()
Attention: Si votre SVG est imbriqué dans un autre document XML (XHTML par exemple) cet objet n’existera pas !
L'interface SVGSVGElement
- SVGSVGElement est l'interface pour l'élément 'svg'. Cette interface contient des méthodes utilitaires variées diverses couramment employées, telles que des opérations matricielles et la capacité de contrôler le moment du ré-affichage sur les appareils de rendu visuel....
Eléments utiles du XML DOM2
L'interface Document
L'interface Document représente le document XML entier. Donc soit le document SVG standalone ou encore le document XML ou HTML dans lequel SVG est imbriqué
L'interface Node
L'interface Node est le type de données principal pour tous les modèles DOM. Il représente un seul nœud dans l'arbre du document
- Le plupart des classes implémentent la plupart des méthodes (cela veut dire que pour manipuler un élément SVG, vous pouvez utiliser des méthodes "Node").
- Ainsi, les attributs nodeName , nodeValue et attributes forment un mécanisme pour obtenir une information sur un nœud, sans devoir faire appel à des interfaces dérivées spécifiques. (voir exemple suivant)
- Sinon, il existe plein de méthodes pour connaître et manipuler les enfants.
L'interface Element
- L'interface Element représente un élément dans un document XML. Les éléments peuvent avoir des attributs associés.
getAttribute ("string")
Ramène une valeur d'attribut par son nom
element = ... // objet qui représente un élément element.getAttribute("r")
setAttribute ("name", "value")
Ajoute un nouvel attribut. Si un attribut avec ce nom est déjà présent dans l'élément, sa valeur est changée pour celle du paramètre value. Exemples d'application :
element.setAttribute ("fill", "yellow"); element.setAttribute ("font-weight","bold"); element.setAttribute ("stroke-width", "25.5px");
getElementById ("id")
Retourne l’élément dont l'ID est donné par l'attribut elementId. Si un tel élément n'existe pas, cela retourne null.
Il s'agit ici d'une méthode très importante pour réaliser facilement des animations, car elle vous permet d’identifier facilement n’importe quel élément enfant qui a un identificateur (attribut "id").
eye_right = svgdoc.getElementById("eyeRightId");
L’interface Event
permet de fournir des informations sur un événement, par ex. l’attribut target
function infos(evt) { var element = evt.target ; .... }
<circle onclick="infos(evt)" .... />
Exemple DOM alert
Montre quelques méthodes DOM simples
- http://tecfa.unige.ch/guides/svg/ex/svg-dom/dom-alert.svg (animation)
- http://tecfa.unige.ch/guides/svg/ex/svg-dom/
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="7cm" height="6cm" viewBox="0 0 600 500"
xmlns="http://www.w3.org/2000/svg">
<desc>Exemple qui affiche des alert suite à un evenement onclick
</desc>
<script type="text/ecmascript"> <![CDATA[
function infos(evt) {
var element = evt.target;
el_name = element.nodeName;
el_attributes = element.attributes;
circle_size = element.getAttribute("r")
display_text = "Element name = " + el_name;
display_text += " \nAttributes = " + el_attributes;
display_text += " \nCircle size = " + circle_size;
alert(display_text);
element.setAttribute("fill", "yellow");
}
]]> </script>
<!-- S'execute a chaque clic -->
<circle onclick="infos(evt)" cx="300" cy="225" r="100" fill="red"/>
<text x="300" y="480"
font-family="Verdana" font-size="32" text-anchor="middle">
Cliquer sur le cercle et lire le popup ...
</text>
</svg>
Gestionnaire d'événements SVG
Voici quelques-uns des plus importants gestionnaires d'événements SVG: (Pour une liste complète, voir: W3C-SPEC)
- onmouseover: exécuté lorsque le curseur se déplace au-dessus d'un objet
- onmouseout: exécuté lorsque le curseur quitte un objet
- onmousemove: exécuté lorsque le curseur se déplace sur un objet
- onclick: exécuté quand l'utilisateur clique sur un objet
- onload: déclenché lorsqu'un fichier SVG a été chargé
- onzoom: déclenché après que l'utilisateur change le niveau du zoom, soit par une interaction directe de l'utilisateur ou de tout changement à la propriété currentScale disponible sur l'interface SVGSVGElement.
- onscroll: déclenché lorsque l'utilisateur fait défiler un svg graphiques
- onresize: déclenché lorsqu'un document a été redimensionnée
Exemple DOM simple
- http://tecfa.unige.ch/guides/svg/ex/svg-dom/omme-dom1.svg (animation)
- http://tecfa.unige.ch/guides/svg/ex/svg-dom/omme.svg (dessin de départ)
- http://tecfa.unige.ch/guides/svg/ex/svg-dom/
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Created with Inkscape (http://www.inkscape.org/)
Daniel Schneider @ tecfa.unige.ch (DKS)
March 2005
Modified some Inkscape output: missing doctype, opacity
Added script and events
-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
height="600.00000" width="800.00000"
y="0.00000000" x="0.00000000"
version="1.0">
<title>Simple Interactivity with Dom</title>
<desc>This is a simple SVG-DOM demo. Clicking on buttons will change the face, i.e. modifiy XML/SMIL attributes. The drawing was made (quickly) with Inkscape. I did not try to change CSS styles, so I made a few manual changes to the original static SVG which is in file omme.svg</desc>
<defs>
<script type="text/ecmascript">
<![CDATA[
// variables globales qu'on utilise dans les 2 fonctions
var svgdoc, eye_right, eye_left, mouth_angry, mouth_happy, mouth_sad ;
// set to 0 in production, 1 for things to debug, 2 for things fixed
// var debug = 2;
var debug = 1;
function init (big_bang) {
svgdoc = big_bang.target.ownerDocument; // instance of the document
eye_right = svgdoc.getElementById("eyeRightId"); // getElementById()
eye_left = svgdoc.getElementById("eyeLeftId");
if (debug==2) alert("eyeLeftId = " + eye_left);
mouth_angry = svgdoc.getElementById("angry");
mouth_happy = svgdoc.getElementById("path1363");
mouth_sad = svgdoc.getElementById("path2168");
if (debug==2) alert ("The document did load nicely, global variables are defined");
}
function face_change(eye_color, emotion) {
eye_left.setAttribute("fill", eye_color);
eye_right.setAttribute("fill", eye_color);
if (debug==2) alert ("mouth emotion =" + emotion);
switch (emotion) {
case mouth_angry:
mouth_angry.setAttribute ("visibility","visible");
mouth_happy.setAttribute ("visibility","hidden");
mouth_sad.setAttribute ("visibility","hidden");
break;
case mouth_happy:
mouth_angry.setAttribute ("visibility","hidden");
mouth_happy.setAttribute ("visibility","visible");
mouth_sad.setAttribute ("visibility","hidden");
break;
case mouth_sad:
mouth_angry.setAttribute ("visibility","hidden");
mouth_happy.setAttribute ("visibility","hidden");
mouth_sad.setAttribute ("visibility","visible");
break;
}
}
function button_click(evt) {
var button = evt.target;
var currentButton = button.getAttribute("id");
if (debug==2) alert ("button =" + currentButton);
if (debug==2) alert ("eye_left,style = " + eye_left.getAttribute('style') + " fill = " + eye_left.getAttribute('fill') );
if (currentButton == "blue_button") {
face_change ("blue", mouth_happy );
}
else if (currentButton == "rect1333") {
face_change ("red", mouth_angry);
}
else {
face_change ("black", mouth_sad);
}
}
]]> </script></defs>
<desc>This inner svg is some hack: onload will not work with the top-level svg. We do need init to work in order to get at the document root (this is not like normal XML it seems).</desc>
<svg onload="init(evt)">
<desc>Below is the definition of the head, eyes and mouth </desc>
<rect
id="rect1303"
style="fill:#edca5e;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
y="314.00000"
x="177.37018"
height="188.00000"
width="122.00000" />
<path
id="path1301"
style="fill:#edca5e;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
transform="translate(-284.0000,-122.0000)"
d="M 676.00000,319.00000 C 676.00000,400.18586 606.60414,466.00000 521.00000,466.00000 C 435.39586,466.00000 366.00000,400.18586 366.00000,319.00000 C 366.00000,237.81414 435.39586,172.00000 521.00000,172.00000 C 606.60414,172.00000 676.00000,237.81414 676.00000,319.00000 L 676.00000,319.00000 z " />
<desc>Below we have the 2 eyes. Both are deep green for starters.</desc>
<path
id="eyeLeftId"
fill = "#00ff00"
style="fill-opacity:1;stroke:#000000;stroke-width:2.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
transform="translate(-284.0000,-122.0000)"
d="M 492.00000,311.00000 C 492.00000,330.32997 475.43454,346.00000 455.00000,346.00000 C 434.56546,346.00000 418.00000,330.32997 418.00000,311.00000 C 418.00000,291.67003 434.56546,276.00000 455.00000,276.00000 C 475.43454,276.00000 492.00000,291.67003 492.00000,311.00000 L 492.00000,311.00000 z " />
<path
id="eyeRightId"
fill = "#00ff00"
style="fill-opacity:0.75000000;stroke:#000000;stroke-width:2.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
transform="translate(-153.0000,-125.0000)"
d="M 492.00000,311.00000 C 492.00000,330.32997 475.43454,346.00000 455.00000,346.00000 C 434.56546,346.00000 418.00000,330.32997 418.00000,311.00000 C 418.00000,291.67003 434.56546,276.00000 455.00000,276.00000 C 475.43454,276.00000 492.00000,291.67003 492.00000,311.00000 L 492.00000,311.00000 z " />
<desc>Below we have 3 mouthes</desc>
<path
id="path1363"
visibility="visibile"
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:14.173228;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
d="M 154.14365,255.24862 C 154.14365,255.24862 169.06078,300.00000 240.33150,298.34255 C 311.60221,296.68509 326.51934,246.96133 326.51934,246.96133" />
<path
id="path2168"
visibility="hidden"
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:14.173228;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
d="M 150.82873,294.22136 C 150.82873,294.22136 165.74586,249.46998 237.01658,251.12743 C 308.28729,252.78489 323.20442,302.50865 323.20442,302.50865" />
<path
id="angry"
visibility="hidden"
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:14.173228;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
d="M 139.22652,280.11050 L 339.77901,278.45304" />
<desc>Below are the 3 buttons to the right </desc>
<rect
onclick="button_click(evt)"
id="rect1333"
style="fill:#ff0000;fill-opacity:1.0000000;stroke-width:14.173228;stroke-miterlimit:4.0000000"
y="197.23756"
x="474.03317"
height="79.558014"
width="77.900551" />
<rect
onclick="button_click(evt)"
id="rect1335"
style="stroke-width:14.173228;stroke-miterlimit:4.0000000"
y="416.02209"
x="474.03317"
height="79.558014"
width="77.900551" />
<rect
onclick="button_click(evt)"
id="blue_button"
style="fill:#0000ff;fill-opacity:1.0000000;stroke-width:14.173228;stroke-miterlimit:4.0000000"
y="306.62982"
x="474.03317"
height="79.558014"
width="77.900551" />
</svg>
</svg>
Note sur la fabrication du dessin:
Le dessin a été fait avec le logiciel InkScape (qui est un très bon logiciel gratuit qui produit du SVG statique), mais il ne fait pas (encore) du dynamique
Il fallait faire 2-3 retouches:
- remplacer des éléments CSS par des attributs XML (je ne sais pas comment accéder facilement à un élément CSS dans une longe chaîne via le DOM)
- changer quelques valeurs (opacité, couleurs)
- corriger qq. bugs mineurs
- changer qq. id pour des raisons pédagogiques
- Il faut identifier les id de certains éléments
- Trop souvent ce type de logiciel produit des path (au lieu d’une cercle par ex.), donc on ne s’y retrouve pas dans le code.
- Toutefois, on cliquant sur l’objet dans l’éditeur on peut le voir dans l’arbre DOM dans l’éditeur XML.
Il suffit de noter l’id sur une feuille de papier ou encore de le changer en une valeur intelligible.
Cet exemple:
- implémente des boutons (à droite) qui changent l’émotion du visage.
- les yeux changent de couleur (on aurait pu faire cela sans DOM)
- différentes "bouches" sont cachées/montrées et pour cela il faut un script à mon avis.
Voici quelques éléments du dessin SVG:
- Voici l’oeil gauche produit par Inkscape, vert au départ.
<path id="eyeLeftId" fill = "#00ff00" style="fill-opacity:1;stroke:#000000;stroke-width:2.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" transform="translate(-284.0000,-122.0000)" d="M 492.00000,311.00000 C 492.00000,330.32997 475.43454,346.00000 455.00000,346.00000 C 434.56546,346.00000 418.00000,330.32997 418.00000,311.00000 C 418.00000,291.67003 434.56546,276.00000 455.00000,276.00000 C 475.43454,276.00000 492.00000,291.67003 492.00000,311.00000 L 492.00000,311.00000 z " />
- Voici la bouche "angry", une simple ligne (cachée au départ)
<path id="angry" visibility="hidden" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:14.173228;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" d="M 139.22652,280.11050 L 339.77901,278.45304" />
- Voici le bouton (rouge) qui déclenche le visage "angry"
<rect onclick="button_click(evt)" id="rect1333" style="fill:#ff0000;fill-opacity:1;stroke-width:14.173228" y="197.23756" x="474.03317" height="79.558014" width="77.900551" />
Les event handlers
Lorsque l’utilisateur clique sur un des rectangles à droite, un script se déclenche
onclick="button_click(evt)"
Les variables globales du script
// variables globales qu'on utilise dans les 2 fonctions var svgdoc, eye_right, eye_left, mouth_angry, mouth_happy, mouth_sad ;
La fonction d’initialisation sert à trouver les objets qu’on veut animer:
function init (big_bang) { svgdoc = big_bang.target.ownerDocument; // instance of the document eye_right = svgdoc.getElementById("eyeRightId"); // getElementById() eye_left = svgdoc.getElementById("eyeLeftId"); mouth_angry = svgdoc.getElementById("angry"); mouth_happy = svgdoc.getElementById("path1363"); mouth_sad = svgdoc.getElementById("path2168"); }
La fonction button_click qui gère les clics de l’utilisateur sur les rectangles:
function button_click(evt) { var button = evt.target; var currentButton = button.getAttribute("id"); if (currentButton == "blue_button") { face_change ("blue", mouth_happy ); } else if (currentButton == "rect1333") { face_change ("red", mouth_angry); } else { face_change ("black", mouth_sad); } }
La fonction button_click reçoit un objet informatique (le paramètre "evt") qui contient toutes les informations sur le click (et surtout l’objet sur lequel on a cliqué) et qu’on va sauver dans une variable "button" ici.
var button = evt.target;
la propriété "target" de l’objet "evt" référence l’objet sur lequel on a cliqué
var currentButton = button.getAttribute("id");
Ensuite on identifie le nom du bouton sur lequel on a cliqué (on lui demande son "id"). En fonction de l’id du bouton (donc 1 des 3 rectangles) on appelle une fonction face_change qui va transformer le visage.
face_change ("black", mouth_sad);
Le premier argument donné est une couleur de cheveux (blue, red ou black). Le 2ème est une variable associée à l’objet qu’il faut utiliser pour dessiner la bouche
La fonction face_change:
function face_change(eye_color, emotion) {
eye_left.setAttribute("fill", eye_color);
eye_right.setAttribute("fill", eye_color);
if (debug==2) alert ("mouth emotion =" + emotion);
switch (emotion) {
case mouth_angry:
mouth_angry.setAttribute ("visibility","visible");
mouth_happy.setAttribute ("visibility","hidden");
mouth_sad.setAttribute ("visibility","hidden");
break;
case mouth_happy:
mouth_angry.setAttribute ("visibility","hidden");
mouth_happy.setAttribute ("visibility","visible");
mouth_sad.setAttribute ("visibility","hidden");
break;
case mouth_sad:
mouth_angry.setAttribute ("visibility","hidden");
mouth_happy.setAttribute ("visibility","hidden");
mouth_sad.setAttribute ("visibility","visible");
break;
}
L’instruction switch nous permet en fonction de l’objet "emotion/bouche" transmise de rendre cet objet visible et les autres invisibles.
Ceci dit, au lieu de rendre visible/invisible un objet on aurait aussi pu l’enlever/ajouter de la scène. Avec une balise "<g>" on peut regrouper des enfants (dessin de la "bouche"). Ensuite, avec le DOM, on peut en ajouter ou enlever
Animation avec le DOM
Exemple 5-1: Exemple dom01 de la spécification française
- http://www.yoyodesign.org/doc/w3c/svg1/animate.html (home de la traduction française de la spécification SVG 1.0)
- http://tecfa.unige.ch/guides/svg/ex/svg-w3c/dom01.svg
- http://tecfa.unige.ch/guides/svg/ex/svg-w3c/
A notre avis, il faut surtout utiliser cette fonctionnalité (au lieu des balises animation de SVG):
- lorsque certaines types d’animation et d’interpolation n’existent pas, par exemple un rectangle qui se promène sur l’écran au hasard (on ne connaît pas son chemin)
- lorsqu’on utilise un navigateur de type Firefox qui n’implémente pas encore les animations.
Bibliothèques JavaScript
Une autre possibilité est de créer, animer et/ou manipuler les éléments SVG à l'aide d'une bibliothèque JavaScript. Ces bibliothèques mettent à disposition une interface de programmation (API) qui permet d'interagir avec les éléments SVG. Voici deux exemples de bibliothèques :