Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Créer un diaporama pas à pas - 3 - Améliorer la transition entre les images

Compatible ActionScript 2. Cliquer pour en savoir plus sur les compatibilités.Par lilive (Olivier Tarasse), le 16 juin 2008

Objectif

Ce tutoriel est le troisième de la série commencée ici. Cette série de tutoriaux propose la création d'un diaporama en ligne, avec explications détaillées et à l'usage des débutants en ActionScript 2.

Dans la première partie nous avons vu comment afficher une image externe. Dans la deuxième nous avons ajouté les boutons permettant de faire défiler les images. Dans cette partie, nous partirons de ce point, et nous allons améliorer la transition entre les images.

Jusque-là, l'image disparaissait le temps du chargement, ce qui laissait un vide inutile et disgracieux (si, si) entre les images. Nous allons faire en sorte qu'une fois que l'utilisateur clique sur un bouton, l'ancienne image reste affichée jusqu'au chargement complet de la nouvelle image.

Deux bons dessins valant mieux qu'un long discours :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.
Le point où nous en sommes

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.
Le point à atteindre


Connaissances requises pour la troisième partie

Rien de plus que pour les parties précédentes, chouette.

Comment utiliser ce tutoriel

Comme dans les parties précédentes, le code utilisé tout au long de ce tutoriel se retrouve intégralement en pièce jointe à cet article. Pour vous procurer ces fichiers joints, voyez en bas de page : 1)


I - La stratégie

Nous en étions donc arrivés à créer sur la scène un MovieClip nommé image et à charger dedans des images externes. Nous avions également placé deux MovieClip boutons, lastBtn et nextBtn, qui commandent le changement des images.

Le code qui réalise cela, et qui est le code de départ pour le présent article, est:

var imageMC:MovieClip = this.createEmptyMovieClip("image", this.getNextHighestDepth());
imageMC.loadMovie("images/image0.jpg");
 
var imageActuelle:Number = 0;
 
function chargerImageSuivante() {
	imageActuelle++ ;
	if (imageActuelle == 4) imageActuelle = 0;
	imageMC.loadMovie("images/image" + imageActuelle + ".jpg");
}
 
function chargerImagePrecedente() {
	imageActuelle-- ;
	if (imageActuelle == -1) imageActuelle = 3;
	imageMC.loadMovie("images/image" + imageActuelle + ".jpg");
}
 
var nextBtn:MovieClip = this["nextBtn"];
nextBtn.onPress = chargerImageSuivante;
 
var lastBtn:MovieClip = this["lastBtn"];
lastBtn.onPress = chargerImagePrecedente;

Quand un bouton est cliqué, la méthode loadMovie du MovieClip imageMC est appelée pour charger une autre image. En conséquent, l'image actuellement affichée disparaît, le chargement commence, et la nouvelle image apparaît quand le chargement est terminé. Pendant le temps du chargement, plus ou moins long selon la taille de l'image en octets (on dit son poids), la scène reste vide.

En passant, remarquons que ce temps diminue quand on revient sur une image déjà affichée une fois. Ceci est du au fait que les images chargées récemment sont mises en cache, c'est-à-dire copiées dans un répertoire temporaire de votre disque dur.

Remarquons également que ce problème est quasiment inexistant quand vous testez le .swf en local (les fichiers sont chez vous) car le temps de chargement des images depuis votre disque dur est très rapide.

Comment supprimer le temps où aucune image n'est affichée? Nous allons utiliser la technique suivante:

Au lieu d'avoir un seul MovieClip pour charger et afficher les images, nous allons en mettre deux. Comme expliqué en première partie, ces 2 MovieClips auront chacun une profondeur. L'un sera “devant”, l'autre “derrière”. Donc si chacun de ces MovieClip contient une image, on verra seulement l'image de celui qui est “devant”.

L'astuce consiste à toujours charger l'image dans le MovieClip qui est derrière, et à le faire passer devant une fois que le chargement est terminé. Ainsi nous passerons d'une image à l'autre sans que la scène reste vide.

Ceci suppose que nous avons un moyen de savoir quand le chargement est terminé, pour effectuer la permutation des profondeur à ce moment là. Ce qui me permet d'introduire un nouvel acteur, incontournable dès qu'il s'agit de charger des images proprement:


II - MovieClipLoader, le spécialiste du chargement

Voici donc un nouveau type d'objet à notre palmarès, nommé MovieClipLoader. Un objet de ce type permet de gérer de façon très commode le chargement de fichiers externes. C'est grâce à lui que nous allons surveiller si les chargements sont terminés. C'est aussi lui qui par la suite nous permettra d'afficher les barres de progression des chargements en cours.

Familiarisons-nous d'abord un peu avec lui, avant d'aller plus loin.

1- Charger une image avec MovieClipLoader

Voici le code permettant de charger l'image image0.jpg dans un clip imageMC:

var mcl:MovieClipLoader = new MovieClipLoader();
mcl.loadClip("images/image0.jpg", imageMC);

Ecrire new MovieClipLoader() demande à flash de créer un nouvel objet de classe MovieClipLoader.

Le mot classe ne veut pas dire que c'est un objet qui a la classe. C'est juste le terme consacré. De même les MovieClip sont des objets de classe MovieClip. C'est un terme que l'on utilise en programmation orientée objet (POO). En ces termes, vous seriez un objet de classe Humain. On peut dire que la classe est le “modèle”, ou le “moule”, d'après lequel est construit l'objet. Nous n'en dirons pas plus à ce sujet pour l'instant, sachez juste qu'en suivant ce tutoriel vous êtes doucement en train de vous familiariser avec la POO.

var mcl:MovieClipLoader = new MovieClipLoader() demande donc de créer un nouvel objet de classe MovieClipLoader (en raccourci on dit “créer un nouveau MovieClipLoader”) et de stocker sa référence dans une nouvelle variable. Quand nous voudrons désigner ce nouvel objet, nous le désignerons par la variable mcl.

Un objet de classe MovieClipLoader (en raccourci on dit “un MovieClipLoader”) a une méthode nommée loadClip. Cette méthode permet de demander au MovieClipLoader de charger dans un MovieClip un fichier externe, comme un autre .swf, ou dans notre cas une image .jpg . Cette méthode attend 2 paramètres. En premier paramètre, l'url du fichier à charger. En deuxième paramètre, une référence au MovieClip dans lequel charger le fichier.

Donc mcl.loadClip(“images/image0.jpg”, imageMC) demande à mcl de commencer à charger dans imageMC le fichier images/image0.jpg.

2- Exercice

A titre d'exercice, vous pouvez essayer de remplacer tous les loadMovie du code de départ de l'article par cette nouvelle solution. Au résultat cela ne devrait rien changer.

Voici la solution:

var imageMC:MovieClip = this.createEmptyMovieClip("image", this.getNextHighestDepth());
 
var mcl:MovieClipLoader = new MovieClipLoader();
mcl.loadClip("images/image0.jpg", imageMC);
 
var imageActuelle:Number = 0;
 
function chargerImageSuivante() {
	imageActuelle++ ;
	if (imageActuelle == 4) imageActuelle = 0;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageMC);
}
 
function chargerImagePrecedente() {
	imageActuelle-- ;
	if (imageActuelle == -1) imageActuelle = 3;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageMC);
}
 
var nextBtn:MovieClip = this["nextBtn"];
nextBtn.onPress = chargerImageSuivante;
 
var lastBtn:MovieClip = this["lastBtn"];
lastBtn.onPress = chargerImagePrecedente;

Pour vous procurer les fichiers joints, voyez en bas de page : 2)


III - Détecter la fin du chargement de l'image - L'évènement onLoadInit

Maintenant nous allons voir en quoi MovieClipLoader nous permet de détecter que le chargement est terminé.

1- Le code

Un MovieClipLoader émet l'évènement onLoadInit quand le chargement qui lui a été demandé est terminé et que l'image apparaît. Il nous faut écouter cet évènement pour y réagir. Cela se passe ainsi:

var mcl:MovieClipLoader = new MovieClipLoader();
 
var mclListener:Object = new Object();
mclListener.onLoadInit = function () {
	trace("Le chargement est terminé");
}
mcl.addListener(mclListener);
 
mcl.loadClip("images/image0.jpg", imageMC);

2- Explications

var mclListener:Object = new Object() crée un nouvel objet de classe Object. Cette classe est une classe “de base” qui permet de créer des objets qui “ne savent rien faire de spécial”. Comme il ne sait rien faire, nous allons l'instruire, en lui ajoutant une méthode:

mclListener.onLoadInit = function () {
trace(“Le chargement est terminé”);
}

Ce code munit le nouvel objet d'une méthode onLoadInit. Si cette méthode est exécutée elle affichera “Le chargement est terminé” dans la fenêtre de sortie.

mcl.addListener(mclListener) ajoute le nouvel objet à la liste des écouteurs de mcl. C'est-à-dire que quand mcl émettra des évènements, les fonctions correspondantes de ses écouteurs seront exécutées.

Donc si on demande à mcl de charger un fichier, avec loadClip, mcl émettra l'évènement onLoadInit à la fin du chargement. Les méthodes onLoadInit des objets qui écoutent mcl seront alors exécutées. Comme mclListener écoute mcl, et que mclListener à une méthode onLoadInit, cette méthode sera exécutée, et “Le chargement est terminé” apparaîtra dans la fenêtre de sortie.

Essayez, vous devriez voir le message apparaître à chaque changement d'image.

IV- Permuter les MovieClip

Bien. Ainsi équipés d'un MovieClipLoader, nous pouvons reprendre notre fil.

1- Le code

var imageChargementMC:MovieClip = this.createEmptyMovieClip("image1",this.getNextHighestDepth());
var imageCouranteMC:MovieClip = this.createEmptyMovieClip("image2",this.getNextHighestDepth());
 
var mcl:MovieClipLoader = new MovieClipLoader();
 
var mclListener:Object = new Object();
mclListener.onLoadInit = function () {
	imageChargementMC.swapDepths(imageCouranteMC);
	var temp:MovieClip = imageCouranteMC;
	imageCouranteMC = imageChargementMC;
	imageChargementMC = temp;
}
mcl.addListener(mclListener);
 
mcl.loadClip("images/image0.jpg", imageChargementMC);
 
var imageActuelle:Number = 0;
 
function chargerImageSuivante() {
	imageActuelle++ ;
	if (imageActuelle == 4) imageActuelle = 0;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageChargementMC);
}
 
function chargerImagePrecedente() {
	imageActuelle-- ;
	if (imageActuelle == -1) imageActuelle = 3;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageChargementMC);
}
 
var nextBtn:MovieClip = this["nextBtn"];
nextBtn.onPress = chargerImageSuivante;
 
var lastBtn:MovieClip = this["lastBtn"];
lastBtn.onPress = chargerImagePrecedente;

2- Le résultat

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

Pour vous procurer les fichiers joints, voyez en bas de page : 3)

3- Analyse du code

Reprenons le code point par point:

var imageChargementMC:MovieClip = this.createEmptyMovieClip("image1",this.getNextHighestDepth());
var imageCouranteMC:MovieClip = this.createEmptyMovieClip("image2",this.getNextHighestDepth());

Nous créons sur la scène deux MovieClip vides nommés image1 et image2. Ils vont nous servir à charger les images, avec la stratégie dont nous avons parlé en introduction.

Nous créons deux variables pour faire référence à ces MovieClips: imageChargementMC et imageCouranteMC.

Par la suite, nous nous débrouillerons pour que imageCouranteMC désigne toujours le MovieClip qui contient l'image actuellement affichée, au premier plan, et pour que imageChargementMC désigne toujours le clip qui est en train de se charger, ou qui attend pour le faire, au second plan.

Nous chargeons donc la première image dans imageChargementMC:

mcl.loadClip("images/image0.jpg", imageChargementMC);

Et nous définissons le code qui permet de changer d'image:

function chargerImageSuivante() {
	imageActuelle++ ;
	if (imageActuelle == 4) imageActuelle = 0;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageChargementMC);
}
function chargerImagePrecedente() {
	imageActuelle-- ;
	if (imageActuelle == -1) imageActuelle = 3;
	mcl.loadClip("images/image" + imageActuelle + ".jpg", imageChargementMC);
}

Donc au clic la nouvelle image sera chargée dans imageChargementMC.

Le plus délicat est d'écrire le code qui s'exécute à la fin du chargement. Une première proposition aurait pu être, pour faire passer imageChargementMC au premier plan quand le chargement est terminé:

mclListener.onLoadInit = function () {
	imageChargementMC.swapDepths(imageCouranteMC);
}

swapDepths étant une méthode de MovieClip qui permet à un MovieClip d'échanger sa profondeur avec un autre. A la fin du chargement, imageChargementMC qui était “derrière”, va donc passer “devant”, et imageCouranteMC passera “derrière”. On verra donc la dernière image chargée.

Mais ce serait oublier qu'à chaque fois qu'un bouton est cliqué:

mcl.loadClip("images/image" + imageActuelle + ".jpg", imageChargementMC);

est exécuté. Il faut donc que imageChargementMC désigne en permanence le MovieClip qui est à l'arrière plan. Or après imageChargementMC.swapDepths(imageCouranteMC), imageChargementMC désigne le MovieClip du premier plan. C'est pour cela que nous écrivons:

mclListener.onLoadInit = function () {
	imageChargementMC.swapDepths(imageCouranteMC);
	var temp:MovieClip = imageCouranteMC;
	imageCouranteMC = imageChargementMC;
	imageChargementMC = temp;
}

qui échange les MovieClip auxquels font référence imageCouranteMC et imageChargementMC.

Pour faire cela nous avons besoin d'un variable temporaire temp.

Prenons un exemple pour mieux comprendre: Imaginons que imageChargementMC désigne le MovieClip nommé image1, et que imageCouranteMC désigne le MovieClip image2. C'est image2 qui est devant.

imageChargementMC, c'est-à-dire image1, se charge. A la fin du chargement imageChargementMC.swapDepths(imageCouranteMC) est exécuté: image1 passe devant, image2 passe derrière. imageChargementMC désigne toujours image1, imageCouranteMC désigne toujours image2.

var temp:MovieClip = imageCouranteMC : temp désigne le même MovieClip que imageCouranteMC, c'est-à-dire image2

imageCouranteMC = imageChargementMC : imageCouranteMC désigne maintenant le même MovieClip que imageChargementMC, c'est-à-dire image1.

On veut maintenant que imageChargementMC désigne le MovieClip que désignait imageCouranteMC. Mais imageCouranteMC vient d'être modifié. Où trouver son ancienne valeur? C'est pour cela qu'on l'a mise de côté dans une variable temporaire.

imageChargementMC = temp : imageChargementMC désigne le même MovieClip que temp, c'est-à-dire image2, le clip que désignait imageCouranteMC au début de l'échange.

Les MovieClips désignés par imageChargementMC et imageChargementMC se sont bien échangés, et imageChargementMC désigne image2, qui est le MovieClip de derrière.

Tout est donc prêt pour que l'utilisateur puisse cliquer à nouveau, et que imageChargementMC.swapDepths(imageCouranteMC) soit une fois de plus exécuté.


Conclusion

Cet article a donc abordé:

  • La classe MovieClipLoader est son utilisation
  • Les notions de classe et d'objets, en introduction à la POO
  • Un nouvelle manière de gérer des évènements, différente de celle de MovieClip.onPress
  • Comment échanger les valeurs de deux variables
  • Comment permuter les profondeurs de deux MovieClips

Si vous désirez faire vos essais avec tout cela, histoire de vous l'approprier d'avantage, je peux vous suggérer d'essayer de réaliser:

  • Un swf où il y aurait deux MovieClips sur la scène, se chevauchant. Quand on clique sur l'un d'entre eux, le MovieClip qui est derrière passe devant, et vice-versa.
  • Un swf où il y aurait deux MovieClips sur la scène, se chevauchant. Quand on clique sur celui qui est derrière, il passe devant. Quand on clique sur celui qui est devant, rien ne se passe.
  • Un diaporama où le fait de cliquer sur l'image fait passer à l'image suivante (attention, on ne peut définir onPress sur l'image chargée qu'une fois le chargement terminé).
  • Ou tout simplement essayer de réécrire vous-même le code de cet article.

La solution des exercices est également en pièce jointe.Dans l'article suivant, nous utiliserons de nouveau onLoadInit pour déclencher cette fois une transition en fondu entre l'ancienne et la nouvelle image, mais chaque chose en son temps…N'hésitez pas à poser vos questions ou à faire vos remarques sur ce tutoriel sur le forum. Si vous trouvez un passage confus, si vous trouvez des erreurs, vous pouvez répondre au message concernant ce tutoriel ou ouvrir un nouveau sujet. J'apprécierais aussi tout retour positif, ne serait-ce que pour le plaisir de savoir que certains me suivent :-D !


Pour en savoir plus

Pour avoir des précisions ou des renseignements complémentaires à ce tutoriel, vous pouvez consulter 4) :


Navigation: Sommaire page précédente page suivante Index

1) , 2) , 3) Vous pouvez télécharger les fichiers de code correspondants à cet article, les swf compilés, et les images utilisées, le tout dans une archive compressée. Si vous utilisez Flash IDE, cliquez ici. Si vous utilisez un environnement intégrant mtasc et swfmill, cliquez ici
4) Les références à l'aide de Flash concernent la documentation de Flash CS3, accessible par l'IDE de Flash CS3 ou par le site d'Adobe (Support > Documentation).