Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox
Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Nataly, le 12 juin 2010

Introduction
Classe de base (#1)
Classe de base (#2)
Héritage et surcharge (#1)
Héritage et surcharge (#2)
Diffuser des événements
Classe liée
Classe de document
Classe externe : une visionneuse (#1)
Classe externe : une visionneuse (#2)
Classe externe : méthodes statiques

Classe externe : une visionneuse (#1)

Nous voici bientôt arrivés au terme de la randonnée au pays de Poo, et ce nouveau chapitre va être une excellente excuse à mettre en œuvre tout ce qui a été vu jusqu'alors.
L'idée c'est de construire une classe visionneuse ou diaporama, ce qui revient au même…
Justement peut-être nos rangs sont ils grossis de quelques nouveaux arrivés via un moteur de recherche. Bienvenue à vous, sachez seulement que je considère comme acquis (ou en voie d'acquisition, on s'énerve pas) les points précédemment développés.

Je ne développerai pas :
• Ce qu'est une classe, comment ça se construit et les syntaxes dédiées
• Comment définir des méthodes, un constructeur ou des accesseurs
Je vous invite à vous reporter aux pages précédentes pour ces différents points.

Il vous faut aussi savoir appliquer dynamiquement un masque à un clip, et lui appliquer un flou.
On utilisera les classes loader et loaderInfo pour charger les images, mais ça n'a pas à voire directement avec la visionneuse, vous pouvez vous contenter d'admettre les quelques lignes concernées si d'aventure vous n'en êtes pas familiers.

intro

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Ça, c'est ce qu'on imagine obtenir à terme : des visuels qui s'enchainent avec une transition animée via un masque selon le principe illustré là. Vous le constatez, les images sont affichées en boucle, mais la première ne l'est qu'une fois.

Les boutons qui changent le sens de défilement ne font pas partie de la classe mais du fichier de mise en œuvre qui permet d'utiliser l'objet Visionneuse, même chose pour la légende.

La classe ne fait rien d'autre, donc, qu'afficher des visuels dans un clip vide et leur appliquer un masque. On ne va pas créer un symbole de bibliothèque vide juste pour lui associer une classe… On pourrait, mais 'faut rien exagérer non plus, il suffit que la classe s'en charge. Nous pouvons donc rêver d'une classe qu'on utiliserait comme suit :

// .fla
 
visio=new Visionneuse();
visio.addEventListener(MouseEvent.CLICK,marcheArret);
addChild(visio);
[...]

Elle mettrait à notre disposition une méthode marche, une méthode arrêt (ainsi que diverses petites choses qu'on inventera en cours de route), et n'aurait besoin pour fonctionner que d'un clip (animation de transition) et d'une série de visuels qu'on lui passerait sous forme d'un tableau. Du coup on l'initialiserait à la construction comme suit :

var visio:Visionneuse=new Visionneuse(tabPhotos,leMasque);

Ce qui est sympa avec le code, c'est que du rêve à la réalité il n'y a qu'un clavier, dont je vous propose de vous saisir sans plus attendre. C'est parti pour la visionneuse !

Côté .fla

Il nous faudra un fichier .fla de mise en œuvre et un fichier .as pour la classe, les deux étant considérés comme enregistrés dans le même répertoire.
Créons le fla pour commencer.

Charger les images

On sera amenés à utiliser la classe Visionneuse soit avec des visuels sous forme de symboles de la bibliothèque, soit sous forme de fichiers externes. Alors pour le plaisir de frimer qu'on sait tout faire, je vous propose de faire un mixte : charger une première image qui sera un symbole de bibli (la page de garde), les autres seront des images externes.

Mon point de vue étant qu'il vaut mieux écrire cinq fois dix lignes en les testant au fur et à mesure, qu'écrire une fois cinquante lignes qui plantent à l'exé (et qu'on sait même pas où, et qu'on se retrouve à poster deux écrans de code dans le forum sur le mode “au secours ça marche pô chépa pourquoi…” ;)) on va procéder par étapes en vérifiant régulièrement que “jusque là, ça va…”

Avant même d'attaquer la classe, occupons nous donc de fabriquer un tableau qui contiendra les visuels : un symbole de bibliothèque et des photos externes.

Je vous laisse fabriquer le clip pour le premier visuel, pensez à cocher la case exporter pour actionScript (pour en créer une instance dynamiquement), de mon côté je le nomme Mv_Photo0.

Charger les fichiers et fabriquer le tableau
On considère ici des images dans le même répertoire que les deux fichiers .fla et .as, nommées P1.jpg, P2.jpg, P3.jpg…

// .fla
 
var ldrFichier:Loader;
var ldrInfo:LoaderInfo;
 
var tabPhotos:Array=new Array();
var nbPhotos:int=3;
 
var visio:VisioPazapa;
 
var visuelDep:Mv_Photo0= new Mv_Photo0();
tabPhotos.push(visuelDep);
 
charge("P1.jpg");
 
function charge(pNom:String):void {
	ldrFichier= new Loader();
	ldrInfo=ldrFichier.contentLoaderInfo;
	ldrInfo.addEventListener(Event.COMPLETE, Fini);
	ldrFichier.load(new URLRequest(pNom));
}
 
function Fini(e:Event) {
        // remplir le tableau et compter le nb d'éléments
	var nb:int=tabPhotos.push(e.target.loader);
	if (nb<=nbPhotos) {
		// charger le suivant
		charge("P"+nb+".jpg");
	} else {
               // On a tout 
		trace("prêt à déclencher les hostilités : "+ tabPhotos)
	}
}
prêt à déclencher les hostilités : [object Mv_Photo0],[object Loader],[object Loader],[object Loader]

Fabriquer le masque

La technique mise en œuvre pour la transition c'est une animation, un clip utilisé comme masque pour dévoiler la photo suivante. Vous pouvez réutiliser celui que vous avez construit ici, pensez seulement à supprimer les images après les interpolations qui n'étaient destinées qu'à permettre un temps d'exposition entre deux photos, on va bien sûr se faire une joie de coder une propriété temps_de_pause :)

La Classe

Préparer la classe et vérifier que "jusque là, ça va".

On a tout ce qu'il faut pour agencer les premières briques de notre gros lego perso. Je vous laisse construire la structure de base de la classe : un constructeur qui trace ses deux paramètres (pTabVisuels, et pMasque) et les deux méthodes marche et arret.
Ici elle se nomme VisioPazapa, faites bien comme vous voulez de votre côté.

// .as
 
package {
	import flash.display.MovieClip;
 
	public class VisioPazapa extends MovieClip {
 
		public function VisioPazapa(pTabVisuels:Array, pMasque:MovieClip):void {
			trace("constructeur visio : " + pTabVisuels + "\nmasque : "+pMasque);
		}
 
		public function marche():void {
			trace("Marche");
		}
 
		public function arret():void {
			trace("Arrêt");
		}
 
	}
}

… et on vérifie immédiatement que tout se déroule comme prévu : une fonction nouvelleVisionneuse (appelée dans fini) qui crée et ajoute une instance de notre classe toute neuve.

// .fla
 
var ldrFichier:Loader;
var ldrInfo:LoaderInfo;
 
var tabPhotos:Array=new Array();
var nbPhotos:int=3;
 
// déclarer un objet VisioPazapa
var visio:VisioPazapa;
 
var visuelDep:Mv_Photo0= new Mv_Photo0();
tabPhotos.push(visuelDep);
 
 
for (var i:int=1; i<=nbPhotos; i++) {
	ldrFichier= new Loader();
	ldrInfo=ldrFichier.contentLoaderInfo;
	ldrInfo.addEventListener(Event.COMPLETE, fini);
	ldrFichier.load(new URLRequest("P"+i+".jpg"));
}
 
function fini(e:Event) {
	var nb:int=tabPhotos.push(e.target.loader);
	if (nb>nbPhotos) {
		trace("prêt à déclencher les hostilités : " +tabPhotos);
                // création de la visionneuse
		nouvelleVisionneuse();
	}
}
// 
function nouvelleVisionneuse() {
        // créer un objet Mv_Masque0
        var leMasque:Mv_Masque0=new Mv_Masque0();
        // nouvelle instance initialisée avec le tableau et le masque
	visio=new VisioPazapa(tabPhotos,leMasque);
        // ajouter à la liste d'afichage
	addChild(visio);
}
prêt à déclencher les hostilités : [object Mv_Photo0],[object Loader],[object Loader],[object Loader]
constructeur visio : [object Mv_Photo0],[object Loader],[object Loader],[object Loader]
masque : [object Mv_Masque0]

Ajouter le masque

Pas très visuel tout ça… Oui on dispose bien de tout l'attirail nécessaire : un clip futur masque et un tableau d'images, mais bon… on en fait quoi ?
Dans un premier temps on ajoute le masque, ensuite on s'occupera des couples de visuels.

Comme on imagine bien qu'on aura besoin du masque et du tableau d'un peu partout dans la classe (pas uniquement depuis le constructeur à l'initialisation), on sort deux globales privées : masque et tabVisuels. On applique un flou au masque, on l'ajoute à la liste d'affichage.

	import flash.display.MovieClip;
	import flash.filters.BlurFilter;
	import flash.filters.BitmapFilterQuality;
 
	public class VisioPazapa extends MovieClip {
 
		private var tabVisuels:Array;
		private var masque:MovieClip;
 
		public function VisioPazapa(pTabVisuels:Array, pMasque:MovieClip):void {
			trace("constructeur visio : " + pTabVisuels + "\nmasque : "+pMasque);
			tabVisuels=pTabVisuels;
			masque=pMasque;
			masque.gotoAndStop(2);
			masque.filters=[new BlurFilter(10,10,BitmapFilterQuality.HIGH)];
			addChild(masque);
		}

Ça c'est fait.

Qu'on prenne soin d'arrêter la lecture du clip masque dès tout de suite ça ne vous surprend pas, en revanche que j'utilise un gotoAndStop(2), là vous vous dites : elle fatigue la malheureuse !…
Et bien non ! Pour l'instant le stop que vous avez probablement écrit convient tout à fait, mais plus tard il risque de nous envoyer droit dans le mur… On y reviendra… (suspens… tada ! :D)

Afficher les visuels

Le masque c'est fait, il ne reste plus qu'à afficher une paire de visuels, un pour le fond, un autre qui sera dévoilé (masqué par masque). On va s'en débrouiller dans une fonction chargeVisuels, appelée dans le constructeur.

		public function VisioPazapa(pTabVisuels:Array, pMasque:MovieClip):void {
			tabVisuels=pTabVisuels;
			masque=pMasque;
			masque.gotoAndStop(2);
			masque.filters=[new BlurFilter(10,10,BitmapFilterQuality.HIGH)];
			addChild(masque);
                        // les visuels
                        chargeVisuels()
		}

La fonction chargeVisuels

C'est le même principe que détaillé ici, je ne recommence pas ^^

		private function chargeVisuels():void {
			var idxTmp:int=idxSup;
 
			try {
				removeChild(photoFond);
				removeChild(photoRecouvre);
			} catch (e:Error) {
			}
			//au premier passage idxSup = 1 et idxInf = 0;
			photoRecouvre=tabVisuels[idxSup];
			photoFond=tabVisuels[idxInf];
 
			photoRecouvre.mask=_masque;
			photoRecouvre.cacheAsBitmap=true;
			addChildAt(photoRecouvre,0);
			addChildAt(photoFond,0);
 
                        // incrémenter pour le prochain passage
                        idxSup++;
                        // idxSup vaut 1 si supérieur à numPhotoMax 
			idxSup=idxSup>numPhotoMax?1:idxSup;
			idxInf=idxTmp;
		}

Bien sûr, il faut avoir déclaré et valorisé les variables :

		private var idxSup:int=1;
		private var idxInf:int=0;
		private var numPhotoMax:int;
 
		private var photoFond:DisplayObject;
		private var photoRecouvre:DisplayObject;
 
                //[.....]
 
                public function VisioPazapa(pTabVisuels:Array, pMasque:MovieClip):void {
			trace("constructeur visio : " + pTabVisuels + "\nmasque : "+pMasque);
			NumPhotoMax=pTabVisuels.length-1;
 
                //[.....]

… et avoir importé la classe.

	import flash.display.DisplayObject;

On devine bien le visuel d'index 1 derrière l'instance de Mv_Photo0.

La transition

C'est le moment de faire en sorte que les méthodes marche et arrêt fassent autre chose que tracer une bête ligne.

		public function marche() {
			masque.play();
		}
		public function arret() {
			masque.stop();
		}

Dans l'absolu, il suffit maintenant d'ajouter un écouteur à visio et d'écrire une jolie bascule :

function nouvelleVisionneuse() {
	visio=new VisioPazapa(tabPhotos,leMasque);
	visio.addEventListener(MouseEvent.CLICK,marcheArret);
	addChild(visio);
}
//
function marcheArret(me:MouseEvent) {
	if (visio.enMarche) {
		visio.arret();
	} else {
		visio.marche();
	}
}

Râle pas Ronchon ! Non il n'y a pas de propriété enMarche définie dans la classe, mais il faut bien anticiper : puisqu'il est évident qu'on en aura besoin on considère qu'elle existe et, tout de suite derrière, on file dans la classe l'ajouter d'un couple d'accesseurs comme on sait les faire.

		public function set enMarche(pB:Boolean):void {
			_enMarche=pB;
		}
		public function get enMarche():Boolean {
			return _enMarche;
		}

Avec la globale :

		private var _enMarche:Boolean=false;

Puis on s'occupe de modifier la valeur de cette variable dans les méthodes marche et arret :

		public function marche(e:Event=null) {
			trace("marche");
			masque.play();
			_enMarche=true;
		}
		public function arret() {
			trace("arret");
			masque.stop();
			_enMarche=false;
		}

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Et là, youpi ! Ça dévoile :)

Enchainer les images

La belle affaire… Ce qu'on veut c'est qu'à chaque fois que la lecture du masque boucle (revient image 1), un nouveau couple d'image soit chargé… Il faudrait un petit script image 1… il faudrait ajouter à l'instance masque, image 1, un script qui appèlerait chargeVisuels:idea: ! addFrameScript, bien sûr (vous vous souvenez, page précédente ?).

En se souvenant que la première image est numérotée zéro, ça donne :

  masque.addFrameScript(0,chargeVisuels);

On ajoute la ligne dans le constructeur.

		public function VisioPazapa(pTabVisuels:Array, pMasque:MovieClip):void {
			NumPhotoMax=pTabVisuels.length-1;
			tabVisuels=pTabVisuels;
			masque=pMasque;
			masque.gotoAndStop(2);
			masque.filters=[new BlurFilter(10,10,BitmapFilterQuality.HIGH)];
			// ajouter du code image 1 de masque
			masque.addFrameScript(0,chargeVisuels);
			addChild(masque);
                        chargeVisuels();
		}

Et c'est là qu'on est content d'avoir anticipé le gotoAndStop(2).
Hé oui, la méthode addFrameScript recèle bien des surprises quand on l'applique à une image de clip qui se trouve être l'image courante… Je ne vous cache pas que j'ai bien failli y laisser mon intégrité mentale (je synthétiserai plus loin). Pour éviter de nous compliquer la vie, avoir pris soin d'arrêter la tête de lecture image deux, est une ruse qui vaut ce qu'elle vaut, mais garantit un déroulement des choses sur lequel on a vraiment la main 8-)
Du coup, soit on appelle chargeVisuels comme ci-dessus, soit on renvoie la tête de lecture image 1 et la fonction chargeVisuels fraichement associée est invoquée (c'est la version des sources).

masque.gotoAndStop(1);

Et voilà une visionneuse, spartiate, mais tout à fait fonctionnelle…

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Bien sûr on peut souhaiter quelques sophistications supplémentaires : changer le sens de défilement, paramétrer le temps de pause entre deux visuels, atteindre directement un visuel, disposer d'événements pour intercepter le moment où le diaporama boucle, où le changement d'image à lieu…

page suivante -->