Créer un composant dans flash MX2004

Cet article vous explique comment créer un composant dans Flash MX2004 en vous proposant un exemple concret. Je remercie Jérôme et Rmotte pour leur aide précieuse et leurs corrections apportées à ce tuto.

Article lu   fois.

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

1. Introduction

Le but de ce tutoriel est de vous montrer comment créer un composant dans Flash MX 2004. Pour l'appréhender correctement, il est préférable d'avoir déjà de bonnes connaissances en Flash. Surtout en ce qui concerne les clips et les classes en général.

1.1. Qu'est-ce qu'un composant

Un composant est un objet intégrant toute une série de fonctionnalités utilisables dans n'importe quelle animation sans devoir déployer un effort particulier au niveau développement. Les composants sont disponibles dans la fenêtre des composants de Flash MX2004. Contrairement aux composants de Flash MX, ceux de MX 2004 sont compilés, il n'est donc plus possible d'éditer les composants standards tels que Checkbox, button, Scrollpane... L'avantage des composants est principalement leur réutilisabilité et leur paramétrage via la fenêtre des propriétés ou via l'inspecteur des composants. Un autre avantage est aussi que l'on peut distribuer un composant facilement. Si vous êtes indépendant, vous pourriez créer vos propres composants et les distribuer à vos clients. L'avantage est que le code associé au composant est compilé. De ce fait, la discrétion concernant la réalisation et le code source est préservée.

1.2. Quel type de composant nous proposons vous?

Nous vous proposons une bannière d'images. Cette bannière chargera dans un scrollpane les images dont les chemins sont définis dans un fichier XML de votre choix. La structure de ce fichier XML est très simple et sera décrite plus loin. L'utilisation du composant est ultra simple.

1.3. Propriétés de notre composant

Image non disponible

Description des propriétés

Nom de la propriété Valeur(s) possible(s) Description
Alpha true ou false Défini à true, un effet de transparence apparaîtra au survol des images. A false, aucun effet ne sera défini
Fichier Son URL pointant sur l'emplacement du fichier son L'URL indiquera au composant quel fichier son il faut exécuter lors du clic sur une image. Si ce paramètre est vide, aucun son ne sera joué
Fichier XML URL pointant sur l'emplacement du fichier XML L'URL indiquera au composant quel fichier XML contient les chemins des images
Fonction associée Un nom de fonction que vous avez développé La valeur que vous attribuerez éventuellement à ce paramètre doit correspondre au nom d'une fonction que vous avez développé. Cette fonction sera alors déclenchée lorsque l'utilisateur cliquera sur une image. Si vous laissez ce paramètre vide, aucune action ne sera déclenchée lors du clic sur une image. Le composant passe le clip courant en paramètre à votre fonction. Vous comprendrez vite le fonctionnement en visionnant le fichier Banner.fla disponible en téléchargement
Largeur Images un nombre Il sert à déterminer la coordonnée X des images. Si par exemple vous attribuez la valeur 100 à ce paramètre, les images seront positionnées tous les 100 pixels. Si vous avez des images de taille différente, il est préférable d'attribuer la plus grande taille à ce paramètre. Comme vous l'aurez sans doute deviné, il est préférable d'avoir des images de même taille pour un affichage parfait.

1.4. A quoi ressemble-t-il?

Pour visualiser le composant, il vous faut le player 7. Allumez vos enceintes, cliquez sur "Go" et ensuite cliquez sur les images


Cliquez pour lire la vidéo




Note: pour ne pas surcharger le serveur, je n'ai uploadé que 3 images.

2. POO en MX2004

Avec Flash MX 2004, Macromedia a introduit l'actionscript 2 (AS2) et a radicalement changé la philosophie de développement dans Flash. L'AS2 propose à présent des concepts proches de ceux que l'on peut trouver dans Java et C++. De cette manière, ils "standardisent" la programmation objet en Flash et permettent aux développeurs Java et C++ de s'intéresser d'avantage à Flash et de l'appréhender plus rapidement.

2.1. Qu'est-ce que le classpath

Tout d'abord vous devez savoir que toute programmation de classe doit être faite dans un fichier externe à Flash. Les classes doivent être programmées dans les fichiers .as (Flash->nouveau document->fichier actionscript). Ces fichiers .as sont stockés quelque part sur le disque dur. Afin de ne pas restreindre le choix d'emplacement de ces fichiers, Flash utilise des classpath qui pointent vers ces emplacements.

Pour définir votre propre classpath, vous pouvez aller dans le menu Edition -> préférences -> onglet actionscript -> paramètres actionscript 2. Si vous ajoutez un classpath de type "c:\monclasspath\", vous pourrez dorénavant stocker vos fichiers .as dans le répertoire c:\monclasspath\. Vous pouvez ajouter plusieurs classpaths.

2.2. Classe dynamique ou statique

Sans le mot clé "dynamic" précédent le mot clé "class", une classe actionscript 2 est considérée comme statique. Lorsqu'une classe est statique, on ne peut pas lui ajouter des propriétés ou méthodes de manière dynamique.

Lorsqu'une classe est dynamique, on peut lui ajouter autant de propriétés et de méthodes que l'on souhaite via l'occurrence de classe que l'on a instancié.
Exemple:

 
Sélectionnez
//On crée juste une classe vide pour l'exemple
class dvp{
  function dvp(){
 
  }
}
//Dans un fla
var dvpobj:dvp=new dvp();
dvpobj.MaPropriete=1; //Génère une erreur

En ajoutant le mot clé "dynamic" devant le mot clé "class", on sera autorisé à ajouter la propriété "MaPropriete". Il en va de même pour les méthodes.
Notez cependant que cette protection ne paraît valable que lorsque l'on utilise le "strong typing", c'est à dire une déclaration de variable ressemblant à ceci

 
Sélectionnez

var dvpobj:dvp;

Si nous avions déclaré la variable comme suit:

 
Sélectionnez

var dvpobj=new dvp();

Nous n'aurions pas eu de problèmes pour rajouter une propriété ou une méthode. Ceci est à mon sens un bug et ceci est malheureusement valable pour les méthodes et propriétés privées. Espérons que Macromédia réagisse rapidement à ce problème.

Le mot clé "static" s'applique aux propriétés et méthodes d'une classe. Lorsqu'on les préfixe de ce mot clé, elles sont uniquement accessibles au sein même de la classe ou par une classe ayant hérité de celle-ci. Ces méthodes et propriétés ne sont pas accessibles via l'occurrence de la classe.

Exemple:

 
Sélectionnez

class dvp{
  function dvp(){
  }
  static function dvp_message(){
    trace("cette méthode est statique");
  }
}
//Dans un FLA
var dvpobj:dvp=new dvp();
dvpobj.dvp_message(); //Génère une erreur. Par contre, ceci est correct
dvp.dvp_message();
 

2.3. private et public

Une méthode ou propriété privée est une méthode qui ne peut être accédée par une occurrence de classe.

Exemple:

 
Sélectionnez

class dvp{
	function dvp(){
	}
	private function affiche_message():Void{
	  trace("message");
	}
//Dans un fla
var dvpobj:dvp=new dvp();
dvpobj.affiche_message(); //Génère une erreur

En retirant le mot clé "private" devant la déclaration de la méthode ou en le remplaçant par "public", on aurait pu accéder à cette méthode via l'occurrence dvpobj. Comme je l'ai dit ci-dessus, ce n'est valable que lorsque l'on utilise le "strong typing".

2.4. L'héritage

L'héritage s'effectue via le mot clé "extends". Lorsqu'une classe hérite d'une autre classe, elle peut accéder à toutes les propriétés et méthodes de cette classe, même celles déclarées en "private".
La syntaxe est simple:

 
Sélectionnez

class dvp1{
 function dvp1(){
 
 }
 private function affiche_message() :Void{
 	trace("message");
 }
}
//Dans un autre fichier de classe, on définit cette classe:
class dvp2 extends dvp1{
 function dvp2(){
   affiche_message();
 }
}

Etant donné que dvp2 a hérité des propriétés et méthodes de dvp1, on peut directement appeler une méthode de dvp1.
Note:lorsque l'on fait référence à une méthode ou une propriété on peut préfixer cette référence via le mot clé "this".

2.5. interface et implements

Une interface représente une définition de méthodes. Cette définition devra être respectée par les classes implémentant cette interface. L'interface ne peut contenir:

  • de déclaration de propriété
  • d'implémentation de méthode
  • L'usage de méthodes "private" ou "static"

L'interface comprend en somme le prototype des méthodes qui devront être utilisées par les classes qui implémentent cette interface.
Exemple:

 
Sélectionnez
//définition d'une interface
interface dvp_interface {
  function dvp2():Number; 
  function dvp3():String;
}
 
//définition d'une classe implémentant cette interface
class dvp implements dvp_interface{
  function dvp2():Number{
    return 10;
  }
  function dvp3():String{
    return "dvp";
  }
}
//Cette classe est correcte car elle respecte bien l'interface dvp_interface.
class dvp implements dvp_interface{
  function dvp2():String{
    return "dvp";
  }
  function dvp3():String{
    return "dvp";
  }  
}
//dvp_interface. En effet la méthode dvp2 retourne un type String alors qu'elle est censée retourner un Number.

Note: toutes les méthodes définies dans l'interface doivent être implémentées dans une classe qui implémente l'interface. En cas d'omission d'une déclaration de méthode, le compilateur génèrera une erreur.
L'intérêt des interfaces est de pouvoir consolider et valider son code. Si l'on base plusieurs classes sur la même interface, on saura que toutes ces classes implémentent les méthodes définies dans l'interface. Les interfaces permettent en somme d'ajouter un peu de rigueur dans le développement.

3. Etapes de création de notre composant

Maintenant que vous avez vu sommairement les concepts liés aux classes, on peut passer à la pratique. Pour la création du composant bannière, j'ai procédé comme suit:

Etapes
Création d'un clip vide nommé "Banner". Cliquez sur le menu "insertion" -> "New symbol" -> "Movie clip" et nommez le "Banner"
Liaison de la classe Banner dont le code est expliqué plus bas avec le clip "Banner" Affichez la bibliothèque (CTRL+L) -> Cliquez avec le bouton droit sur le clip "Banner", choisissez "Linkage" -> Export for Actionscript(décochez "Export in first frame") ->Dans la zone "AS 2.0 Class", tapez Banner (correspond au nom de la classe Banner.as)-> Cliquez sur Ok
Définition du composant Réaffichez la bibliothèque, cliquez avec le bouton droit sur le clip Banner -> Component definition -> Dans la zone "AS 2.0 Class", tapez Banner -> Cliquez sur Ok -> Si tout s'est bien passé, l'aspect du clip "Banner" a changé. Une icône représentant un composant et le mot "Component" devrait apparaître à côté du clip
Exportation du composant Réaffichez la bibliothèque, cliquez avec le bouton droit sur le clip Banner -> Export SWC file. Le répertoire dans lequel il faut stocker les composants dépend de votre système d'exploitation, pour être certain de trouver ce répertoire, faites une recherche sur le répertoire "Components". Sur XP, ce répertoire se trouve normalement ici:
C:\Documents and Settings\votre_nom_utilisateur\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Components
Redémarrez Flash

4. Code de la classe à associer au composant

Vous l'aurez deviné, il faut bien sûr d'abord écrire la classe avant de procéder aux étapes décrites ci-dessus.

 
Sélectionnez
//Liste des paramètres disponibles dans le panneau des propriétés
/*
Inspectable est une "balise" de type metadata interprètée par flash.
Dans notre exemple, la structure est toujours la même
	-name représente ce qui va être affiché dans le panneau des propriétés
	-variable est le nom de la variable qui stockera la valeur entrée
	-type est le type de variable
	-defaultValue est la valeur par défaut si l'utilisateur n'attribue pas d'autre valeur
	-enumation permet d'afficher une liste de valeurs à l'utilisateur
*/
[Inspectable(name="Largeur Images", variable="imgwidth", type="Number", defaultValue=100)]
[Inspectable(name="Fichier XML", variable="xmlfile", type="String",defaultValue="")]
[Inspectable(name="Fonction associée", variable="onpressevent", type="String",defaultValue="")]
[Inspectable(name="Alpha", variable="playalpha", enumation "true,false" ,type="Boolean",defaultValue=false)]
[Inspectable(name="Fichier Son", variable="soundfile", type="String",defaultValue="")]	
 
dynamic class Banner extends MovieClip {
 public var __imageWidth:Number;
 public var __xmlFile:String;
 private var _XmlParser:XML;
 public var __ImagesArray:Array;
 public var __left:Number=0;
 public var __function:String;
 public var __alpha:Boolean;
 public var __sound:Sound;
 public var __soundFile:String;    
 
//Constructeur
 function Banner(){
   this.init();
 }
 
 /*Initialisation des propriétés avec les valeurs reçues en paramètre via le panneau
 des propriétés du composant.
 */
 function init(){
   __imageWidth=this.imgwidth;
   __xmlFile=this.xmlfile;
   __function=this.onpressevent;
   __alpha=this.playalpha;
//Gestion du son, si le fichier son a été donné en paramètre, on le charge
   __soundFile=this.soundfile;
   if(__soundFile != ""){
     __sound=new Sound();
     __sound.onLoad=function(success){
       if(success){
         this.__soundOk=true;
       }
     }
     __sound.loadSound(__soundFile,false);
   }
 
   if(__xmlFile != ""){
     this.ParseXml();
   }
 } 
 /*Cette fonction parse le fichier XML afin de récupérer les chemins des images.
 Elle est assez simple étant donné que la structure du fichier XML l'est
 */
 private function ParseXml(){
   XmlParser=new XML();
   XmlParser.Owner=this;//Astuce pour lier la méthode onLoad de XML et l'objet courant
   XmlParser.onLoad=function(success){
     if(success){
       XmlParser.Owner.__ImagesArray=new Array();
       for(i=0;i<this.firstChild.childNodes.length;i++){
         if(this.firstChild.childNodes[i].attributes.path != undefined){
//Ici on construit un tableau qui contiendra tous les chemins des images
           XmlParser.Owner.__ImagesArray.push(this.firstChild.childNodes[i].attributes.path);
         }
       }
       XmlParser.Owner.BuildClip();
     }
   }
//Instruction pour charger le fichier XML
   XmlParser.load(__xmlFile);
 }
 
 private function BuildClip(){
//On parcourt notre tableau
   for(i=0;i<__ImagesArray.length;i++){
//On crée un clip vide
     this.createEmptyMovieClip("img"+i,i);i
//Si un nom de fonction a été donné en paramètre, il faut l'affecter à l'évènement onPress du clip
     if(__function != ""){
       this["img"+i].Owner=this;
       this["img"+i].onPress=function(){
         if(this.Owner.__sound.__soundOk){ //Si le son a été chargé
           this.Owner.__sound.start();
         }
         eval(this.Owner.__function)(this);
       }
     }
//Cette partie gère la transparence de l'image selon le paramètre alpha du composant
     if(__alpha){
       this["img"+i].onRollOver=function(){
         this._alpha=50;
       }
       this["img"+i].onRollOut=function(){
         this._alpha=100;
       }
     }
/*On recrée un clip vide car ici aussi il y a une astuce. Pour pouvoir charger l'image dans un clip et attribuer une
action à l'évènement onPress, il faut passer par deux clips vides car le loadMovie "écrase" la méthode onPress affectée.
Donc, on crée un premier clip vide "conteneur" auquel on associe une action à onPress et, dans ce clip, on en crée un 
deuxième qui contiendra l'image.*/
     this["img"+i].createEmptyMovieClip("sub_img"+i,i);
       with (this["img"+i]["sub_img"+i]) {
//On positionne l'image grâce au paramètre "largeur d'images" passé au composant
         _x=this.__left;
         _y=20;
         loadMovie(this.__ImagesArray[i]);
       }
       __left+=__imageWidth;
   }
/*Le composant étant attaché à un clip qui lui même est lié à un scrollpane. On sait que le parent du composant
est le clip et que le parent du clip est le scrollpane. Etant donné que le Scrollpane est probablement le composant 
standard le plus ennuyeux à utiliser  à son comportement pas toujours très cohérent, J'ai été obligé d'appeler la méthode
redraw qui redessine le scrollpane après chargement de son contenu. Sans cet appel, le scroll n'affichait pas tout le contenu
chargé. De sucroît, un simple appel à redraw ne suffisait pas, il fallait absolument l'appeler via un évènement associé au
scrollpane, comme mouseMove ou mouseUP...Si vous trouvez une autre méthode, faites moi signe :-)*/
   if(this._parent._parent != undefined){
     this._parent._parent.onMouseMove=function(){
       this.redraw(true);
     }
   }
 
 }

5. Structure du fichier XML

La structure du fichier XML est on ne peut plus simple. Pour pouvoir utiliser le composant, vous allez devoir créer votre propre fichier XML qui devra OBLIGATOIREMENT respecter cette structure:

 
Sélectionnez

<images>
   <img path="http://stephaneey.developpez.com/cameleon.jpg"></img>
   <img path="http://stephaneey.developpez.com/lemurien.jpg"></img>
   <img path="http://stephaneey.developpez.com/escargot.jpg"></img>
   <img path="http://stephaneey.developpez.com/cameleon.jpg"></img>
   <img path="http://stephaneey.developpez.com/lemurien.jpg"></img>
   <img path="http://stephaneey.developpez.com/escargot.jpg"></img>
</images>   

Pour faciliter la compréhension du mécanisme, le contenu du fichier XML ci-dessus est le même que celui du fichier XML que j'ai utilisé dans la section "A quoi ressemble-t-il?"

L'attribut "path" contient l'url où se trouve l'image à afficher et est récupéré par le composant dans la méthode "ParseXml".

Note: pour des raisons de sécurité, Flash n'autorise pas le chargement de fichier XML ou autre se trouvant dans un autre domaine que le swf. Donc, si votre animation tourne sur http://www.monsite.com/animation.swf, le fichier xml doit aussi se trouver sur http://www.monsite.com/ ou un sous répertoire de cette racine web.

6. Particularité du paramètre fonction du composant

Comme nous l'avons vu plus haut, un paramètre "fonction" est associé au composant et vous permet d'exécuter votre propre fonction lorsque l'utilisateur clique sur une image.

Le composant passe l'instance du clip contenant l'image à cette fonction. Vous devrez donc déclarer un argument à celle-ci, comme montré ci-dessous.

 
Sélectionnez

function ma_fonction(obj){ // l'argument obj contiendra l'instance du clip contenant l'image cliquée
 trace(obj);
}

Cela vous permettra d'exécuter des actions particulières sur votre clip.

7. Intégrer ce composant dans une animation Flash

Pour intégrer le composant dans une animation Flash, il faut procéder aux étapes suivantes:

  • Créez un clip et nommez le comme vous voulez.
  • Insérez-y le composant (drag and drop) sur la scène, aux coordonnées x:0 et y:0 OBLIGATOIREMENT
  • Renseignez les propriétés du composant (le paramètre fonction n'est pas obligatoire)
  • Affichez la bibliothèque, sélectionnez le clip et liez le à actionscript (clic droit->linkage)
  • Revenez sur la scène principale ou dans un autre clip et insérez-y un composant scrollpane (drag and drop)
  • Via le panneau des propriétés du scrollpane, insérez le nom de votre clip dans la propriété contentPath
  • N'oubliez bien sûr pas de créer votre fichier XML comme expliqué en section 5

Et voilà, vous pouvez lancer votre animation!

8. Téléchargement

- Télécharger le fichier zip et dézippez-le sur votre machine.
- Procédez aux étapes décrites en section 3.

9. Conclusion

Vous êtes à présent capable de créer vos propres composants ou de faire évoluer celui-ci. Afin de vous pousser à reproduire les étapes décrites en section 3, j'ai laissé intentionnellement le clip "Developpez.com. Club ..." dans le composant. Si vous désirez l'enlever, il vous faudra recréer le composant. Au cas où vous le recréez, vous devrez changer une ligne de code dans la classe actionscript2. La ligne

 
Sélectionnez

_y=20;

devra être remplaçée par:

 
Sélectionnez

_y=0;

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2004 Developpez. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.