.net - Mai 2005

Simplement avec quelques lignes de code ActionScript et l’aide d’une structuration XML, il est très facile de générer une barre de menu à la volée pour vos animations Flash, Lancez l’animation menu_03.fla, un jeu de menus et sous menus permet de choisir une image. Ouvrez le panneau Action, cliquez sur la première image du calque ‘Valeur’ et donnez à la variable ‘RefFichier’ la valeur ‘menus2’ et à la variable ‘RefBouton’ la valeur ‘Bt_Base3’. Lancez à nouveau l’animation pour visualiser la différence. Grâce à quelques lignes d’ActionScript et à l’utilisation de fichiers XML il est facile de mettre en place une telle souplesse de modification. Nous allons le voir au travers de cet article.
Apercu et télchargement des fichiers nécessaires
Le fichier XML
Un des grands avantages d’XML est de pouvoir facilement structurer le contenu d’un fichier. Prenons l’exemple d’une barre de navigation. A la base, les éléments qui la composent sont des menus, des sous menus, des liens... on pourrait comme cela aller encore plus loin dans le détails en incluant toute sortes d’informations telle que la forme des boutons, les textes des info-bulles, etc. XML va nous permettre de renseigner toutes ces informations dans le degré de complexité voulu.
Avant d’aller plus loin, quelques règles de bases sont nécessaires. Le XML est un langage à balises imbriquées les unes aux autres. Il a beaucoup de similitude avec le HTML, mais la syntaxe y est bien plus rigoureuse. En voici quelques exemples:
- Une seule balise doit composer l’ensemble du document, comme la balise <html> des documents html.
- Les imbrications de balises ne peuvent pas être croisées, <b><i>contenu</b></i> n’est pas valide en XML.
- Chaque balise ouvrante doit posséder une balise fermante, dans le cas de balise simple, comme <img> en html, il faut terminer la balise par un slache, <img src=«lelien.jpg» /> ou <br />.
- Chacune des balises peut avoir un ou plusieurs attributs qui doivent être définis entre guillemet, lien=«lelien.jpg», même pour des valeurs numéraires largeur=«10».
- Les balises ouvrantes et fermantes sont sensibles à la casse, <Balise>contenu</balise> n’est pas valide en XML.
Voilà, on peut débuter la rédaction du document XML. Lancez Note Pad ou (TextEdit sous Mac) et enregistrez le fichier sous « menus.xml ». Pour renseigner des valeurs, il y a deux possibilités, soit comme contenu de balises, soit au travers d’attributs. Afin d’en explorer les deux manières, les menus et les liens seront passés en attribut et les sous menus en élément (ou balise).
Aucun entête de fichier n’est nécessaire car pour l’heure Flash ne les gère pas, l’essentiel est, si possible, d’enregistrer le fichier sous un codage UTF-8. Le fichier XML en est réduit à sa plus simple expression, une balise <menus> incluant des sous balises <menu> et <sousmenu> ainsi que des attributs ‘titre’ et ‘lien’.
<menus>
<menu titre="Légumes">
<sousmenu lien="oign.jpg">Oignons</sousmenu>
<sousmenu lien="poiv.jpg">Poivrons</sousmenu>
</menu>
<menu titre="Fruits">
<sousmenu lien="melo.jpg">Melons</sousmenu>
<sousmenu lien="pech.jpg">Pêches</sousmenu>
<sousmenu lien="citr.jpg">Citrons</sousmenu>
<sousmenu lien="oran.jpg">Oranges</sousmenu>
</menu>
</menus>
Le fichier Flash
Le fichier de description terminé, il faut passer à Flash et à l’ActionScript. Durant cette phase, il va falloir, importer le fichier XML, le transformer en tableau Flash (Array())*,et générer l’affichage des menus correspondants.
Les trois fichier fournis vont tour à tour explorer diverses facettes de cette barre de menu. D'abord le chargement du fichier XML (menu_01.fla), puis viendra la sérialisation du fichier XML en tableau Flash (menu_02.fla) et enfin le dernier explorera la gestion de la barre de navigation (menu_03.fla). Vous allez trouvez ci-dessous le détail de l'exploration des ces trois fichiers.
(*) Deux écoles sont possibles, soit utiliser et faire référence continuellement au modèle XML, soit sérialiser sous forme d’Array(). Pour notre barre de navigation nous allons utiliser un seul symbole ‘Clip’, contenant un bouton. Le bouton contient lui, une variable ‘titre’ qui affichera le libellé. Il faut impérativement exporter ce symbole pour l’action script. Deux possibilités pour obtenir la boîte de dialogue, sélectionnez le symbole puis soit pressez le bouton info de la bibliothèque, soit sélectionnez ‘liaison’ dans le menu contextuel de la bibliothèque. Il faut ensuite choisir ‘exporter pour l’action Script’, ‘exporter dès la première image’, et ne pas oublier de donner comme identifiant le nom ‘Bt_Base’.
--- menu_01.fla --- Chargement et exploration du fichier XML depuis Flash
Le fichier XML est chargé par Flash, puis exploré au niveau de ses balises et attributs. Tout est affiché au fur et à mesure dans une variable ‘Apercu’ présente sur la scène.
calque(Init)
/*
Si le fichier XML n’est pas Unicode, cette instruction permet à
Flash de s’adapterau mode d’encodage du système et
de préserver entre autre les caractères accentués
(si UTF est utilisé pour le fichier XML,
commentez cette ligne par deux slaches ‘//’).
*/
System.useCodepage = true;
/*
Instanciation d'un objet XML
*/
LeMenuXML = new XML();
/*
Lors de la mise en forme du fichier XML, il est souvent utilisé
des tabulations, des retours chariots, etc…
Le player de Flash traitent ces caractères spéciaux comme des balises
qu’il nous faut filtrer.
En plaçant la propriété ignoreWhite=true,
on indique au player Flash de ne pas tenir compte des caractères TAB, CR, LF...
*/
LeMenuXML.ignoreWhite = true;
/*
Déclenchement du chargement du fichier XML.
*/
LeMenuXML.load("menus.xml");
/*
En applicant la fonction onLoad() à l'objet XML
on spécifie les jeux d'instruction à executer
une fois le dernier octet chargé
*/
LeMenuXML.onLoad = function() {
/*
recupération et extraction de la première balise
dans notre cas <menus>
*/
LeMenuXML = LeMenuXML.firstChild;
/*
mise en boucle sur le nombre de balise contenu...
dans notre cas <menu> pour chacune de ces balises
recupération et affichage de l'attribut titre
dans la variable Apercu présente sur la scène
la concaténation de l'instruction \n permet
d'occasionner un retour chariot
*/
for (var i = 0; i<LeMenuXML.childNodes.length; i++) {
var menu = LeMenuXML.childNodes[i].attributes["titre"];
Apercu += menu + "\n";
/*
mise en boucle sur le nombre de balise contenu
dans la balise <menu> dans notre cas <sousmenu>
*/
for (var j = 0; j<LeMenuXML.childNodes[i].childNodes.length; j++) {
/*
pour chacune de ces balises recupération
du contenu de la balise et de l'attribut titre.
Ensuite on les affiche dans la variable Apercu
présente sur la scène.
La concaténation de l'instruction \n permet
d'occasionner un retour chariot
*/
var sousmenu = LeMenuXML.childNodes[i].childNodes[j].firstChild.nodeValue;
var lien = LeMenuXML.childNodes[i].childNodes[j].attributes["lien"];
Apercu += " " + sousmenu + ": " + lien + "\n";
}
}
};
--- menu_02.fla --- Mise en tableau des datas, et génération du menu.
Cette fois lors de l’extraction des datas, ceux ci sont placés dans un tableau Flash, et les menus se positionnent sur la scène.Pour un soucis de clarté, certaines lignes de code ne sont pas commentées. Si vous le souhaitez, vous pouvez vérifier dans le fichier précédent, vous aurez alors les commentaires 'manquants'.
calque (init) - complément
System.useCodepage = true;
LeMenuXML = new XML();
/*
Instanciation d'un objet Array(), permettant de stocker des tableaux
*/
LeMenuArray = new Array();
LeMenuXML.ignoreWhite = true;
LeMenuXML.load("menus.xml");
LeMenuXML.onLoad = function() {
LeMenuXML = LeMenuXML.firstChild;
for (var i = 0; i<LeMenuXML.childNodes.length; i++) {
var menuTemp = LeMenuXML.childNodes[i].attributes["titre"];
/*
Pour chaque balise <menu> un tableau supplémentaire est imbriqué dans le premier,
afin de stocker lesinformations relatives à chacun des menus. Vous pouvez voir sur la scène
le détail d'imbrication du tableau global 'LeMenuArray'
*/
LeMenuArray[i] = new Array();
/*
Deux sous rubriques sont crées dans ce sous tableau ‘menu’, dans laquelle est placé le nom
du menu et ‘sousmenu’ dans laquelle est placé un nouveau tableau qui lui recevra ,
dans la boucle suivante, une à une les informations relatives à l'ensemble des sous
menu.(voir schéma ci-dessous)
*/
LeMenuArray[i]["menu"] = menuTemp;
LeMenuArray[i]["sousmenus"] = new Array();
for (var j = 0; j<LeMenuXML.childNodes[i].childNodes.length; j++) {
/*
Création d'un nouveau tableau qui recevra pour chaque éléments de sous menu, le nom du
sous menu et son lien. Une fois ce tableau créé et rempli, il est placé dans le tableau
précédent. (voir schéma sur la scène)
*/
var smenuTemp = new Array();
smenuTemp["smenu"] = LeMenuXML.childNodes[i].childNodes[j].firstChild.nodeValue;
smenuTemp["lien"] = LeMenuXML.childNodes[i].childNodes[j].attributes["lien"];
LeMenuArray[i]["sousmenus"][j] = smenuTemp
}
}
/*
L'instance LeMenuXML peut maintenant être
libérée de la mémoire
*/
delete LeMenuXML;
/*
Appel de la fonction qui va gérer l'affichage des menus
cette fonction est placée sur le calque suivant 'Menu'
*/
AfficheMenu();
};
calque(Menu)
AfficheMenu = function () {
/*
Un clip vide, nommé ‘menuGlobal’, est créé sur la scène en profondeur 500. Ce clip va contenir
les menus et permettra de les regrouper au sein d'une même instance. Le niveau 500 est arbitraire
et permet de s'assurer qu'aucun clip éventuellement présent sur la scène ne sera écraser
*/
_root.createEmptyMovieClip("MenuGlobal", 500);
/*
Pour chacun des menus, un clone du symbole ‘BT_Base’ (présent et identifié (liaison) dans la
bibliothèque) est attaché au clip ‘menuGlobal’, positionné en x y, identifié par une variable
lequel (qui nous servira plus tard) et sa variable ‘titre’ est rempli avec le libellé du menu.
*/
/*
Attention, le premier élément d'un tableau (Array()) se trouve en index 0 et pas en 1
comme il semblerait logiquement
*/
for (var i = 0; i<LeMenuArray.length; i++) {
_root.MenuGlobal.attachMovie("Bt_Base", "menu"+i, 510+i);
/*
20 correspond à lamarge X à laquelle sera placé le premier bouton, ensuite le second se placera,
à cette marge plus autant de fois la largeur du bouton
*/
_root.MenuGlobal["menu"+i]._x = 20+(i*_root.MenuGlobal["menu"+i]._width);
/*
10 correspond à la marge sur les Y pour placer l'ensemble des boutons attention de bien tenir
compte du point de référence 0 du clip pour un positionnement précis
*/
_root.MenuGlobal["menu"+i]._y = 10;
_root.MenuGlobal["menu"+i].lequel = i;
_root.MenuGlobal["menu"+i].titre = LeMenuArray[i]["menu"];
/*
Enfin, une action de rollover est attachée au bouton (bt)contenu dans ce clone.
Pour l’instant cette fonction trace simplement le nom du menu au survol, mais dans le fichier
suivant, elle sera décommentée et interpellera la fonction afficheSousMenu().
*/
_root.MenuGlobal["menu"+i].bt.onRollOver = function() {
trace(LeMenuArray[this._parent.lequel]["menu"]);
//AfficheSousMenu(this._parent.lequel);
}
}
}
En sélectionnant le symbole ‘Bt_Base’ puis l’icône infos de la bibliothèque, il suffit de l’exporter pour l’ActionScript dès la première image, afin de le rendre disponible au code.
--- menu_03.fla --- Gestion des sous menus et affichage de l’image.
calque(Valeur)
/* L’utilisation de 4 variables nous permet de judicieusement centraliser, et assouplir la modification de certaines parties du code. ‘RefBouton’ précise le symbole à utiliser pour la barre de menu (ligne 4 du calque ‘Menu’), ‘RefFichier’ définie le fichier XML à charger (ligne 22 du calque ‘Init’), et ‘ImageX’ et ‘ImageY’ spécifient quant à elles, la position de l’image à afficher (lignes 2 et 3 du calque ‘Image’). */ RefBouton = "Bt_Base"; RefFichier = "menus"; ImageX = 400; ImageY = 300;
Calque (SousMenu)
/*
Afin de ne pas avoir deux sous menus affichés en même temps, la fonction AfficheSousMenu() commence par retirer
le clip « sousMenuGlobal » éventuellement déjà présent, puis elle reprend le schéma de la fonction précédente.
C’est à dire qu’elle va créer un clip vide global, appelé « SousMenuGlobal », pour contenir les sous menus.
Ce clip est placé en profondeur 600, mais cette fois il sera positionné en fonction du menu qui est survolé.
Dans l’intitulé de la fonction un paramètre est reçu et est identifié par ‘a’. Il est donc ainsi facile de
retrouver toutes les propriétés du menu en invoquant le chemin de cible _root.MenuGlobal[«menu» + a].
*/
AfficheSousMenu = function (a) {
_root.SousMenuGlobal.removeMovieClip()
_root.createEmptyMovieClip("SousMenuGlobal",600);
_root.SousMenuGlobal._x = _root.MenuGlobal["menu" + a]._x;
_root.SousMenuGlobal._y = _root.MenuGlobal["menu" + a]._y + _root.MenuGlobal["menu" + a]._height;
/*
Pour chacun des sous menu un clone du symbole lié, ‘Bt_Base’, est attaché au sous menu global, puis
positionné et libellé. Le lien adéquat lui est attribué et une fonction est attachée au bouton.
Cette fonction va permettre de gérer l’action de notre barre de navigation. Afin de ne pas s’attarder
sur cette finalité, une simple image s’affichera sur la scène pour en matérialiser l’effet (zone 8).
*/
for (var i = 0; i<LeMenuArray[a]["sousmenus"].length; i++) {
_root.SousMenuGlobal.attachMovie(RefBouton,"smenu" + i, 610 + i);
_root.SousMenuGlobal["smenu" + i].titre = LeMenuArray[a]["sousmenus"][i]["smenu"];
_root.SousMenuGlobal["smenu" + i]._x = 0;
_root.SousMenuGlobal["smenu" + i]._y = i * _root.SousMenuGlobal["smenu" + i]._height;
_root.SousMenuGlobal["smenu" + i].lien = LeMenuArray[a]["sousmenus"][i]["lien"];
_root.SousMenuGlobal["smenu" + i].bt.onRelease = function(){
AfficheImage(this._parent.lien);
_root.SousMenuGlobal.removeMovieClip()
}
}
};
Calque (Image)
/*
Un clip vide nommé « image » est placé sur la scène et positionné en fonction des deux variables
‘ImageX’ et ‘ImageY’ vues dans le script de la zone 1. Bien que décrites en fin de commentaires,
ces deux lignes sont exécutées au tout début de l’animation et ne font pas partie
de la fonction de la zone suivante.
*/
_root.createEmptyMovieClip("image", 100);
_root.image._x = ImageX;
_root.image._y = ImageY;
/*
La fonction AfficheImage() est interpellée par le bouton du sous menu cliqué. Un LoadMovie charge l’image
adéquate dans le clip « image ». L’image est identifiée par le paramètre ‘a’ passé par la fonction.
Les images étant dans un dossier « Images », le début du chemin est concaténé à ce paramètre «images/» + a.
*/
AfficheImage = function (a) {
_root.image.loadMovie("Images/"+a);
};






