Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Créer un diaporama pas à pas - 7 - Préchargements des images - 3 - unloadClip, Boucle while et Valeur de retour d'une fonction

Compatible ActionScript 2. Cliquer pour en savoir plus sur les compatibilités.Par lilive (Olivier Tarasse), le 25 août 2008

Objectif

Cette série de tutoriaux, à l'usage des débutants en ActionScript 2, présente des notions fondamentales de programmation par le biais de la réalisation d'un diaporama en ligne.

Si vous n'êtes pas intéressés par la création d'un diaporama, mais que vous lisez cet article pour apprendre certaines notions de programmation, vous pouvez directement vous rendre aux sections suivantes:

Quant au diaporama, nous avons dans l'article précédent intégré le préchargement des images au diaporama 1). Cela fonctionne, mais nous avons remarqué la chose suivante:

Pour pouvoir afficher une image, il faut attendre que toutes les images précédentes soient chargées. Si l'utilisateur veut afficher la dernière image, et clique sur le bouton image précédente au lancement du diaporama, il va devoir attendre le chargement de l'intégralité des images avant d'avoir quelque chose qui s'affiche. De ce point de vue là, notre version du diaporama sans préchargement était plus efficace.

On pourrait objecter qu'il est à priori peu fréquent de rencontrer des utilisateurs qui vont agir ainsi. Mais par la suite, cela deviendra encore plus probable. En effet, nous avons dans le sommaire annoncé que le diaporama, dans sa version finale, intégrera une “barre de miniatures” qui présentera toute les images de l'album en format réduit. L'utilisateur pourra choisir en cliquant sur une miniature l'image qu'il veut afficher en grand. Cette barre de miniature sera visible dès le lancement du diaporama, avant que les images grand format soient chargées. Il deviendra alors très probable qu'un utilisateur souhaite voir une image qui n'est pas encore chargée, si sa version miniature a attiré son regard ou correspond au type d'image qu'il est venu voir.

Nous allons donc dans cet article faire en sorte de charger en priorité l'image que l'utilisateur demande à voir, au lieu de les charger les unes après les autres dans l'ordre croissant, comme nous l'avions fait jusque là.

A la fin de cet article nous aurons le résultat suivant 2):

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


I - Stopper le chargement d'une image en faveur d'une autre - MovieClipLoader.unloadClip()

Pour la clarté des explications de ce chapitre, nous nous placerons dans la situation suivante:

Supposons que le préchargement des images vienne de commencer, que la première image de l'album soit déjà chargée, et que la deuxième image soit en train de le faire. Supposons que l'utilisateur demande à voir la cinquième image. Pour charger et afficher la cinquième image le plus rapidement possible, il conviendra d'arrêter le chargement qui était en cours (la deuxième image) et de lancer celui de la cinquième.

Pourquoi vouloir arrêter le chargement qui était en cours?

1- Le chargement multiple avec un MovieClipLoader

Un MovieClipLoader permet de charger des contenus dans plusieurs MovieClips simultanément. Il est tout à fait possible de demander le chargement de 5 images différentes dans 5 MovieClips différents avec un seul MovieClipLoader. Il suffit d'appeler 5 fois la méthode loadClip en lui donnant les noms des fichiers à charger et les références des MovieClip qui les recevront. Par exemple:

var mc1:MovieClip = this.createEmptyMovieClip("mc1", 1);
var mc2:MovieClip = this.createEmptyMovieClip("mc2", 2);
var mc3:MovieClip = this.createEmptyMovieClip("mc3", 3);
var mc4:MovieClip = this.createEmptyMovieClip("mc4", 4);
var mc5:MovieClip = this.createEmptyMovieClip("mc5", 5);
var mcl:MovieClipLoader = new MovieClipLoader();
mcl.loadClip("image1.jpg", mc1);
mcl.loadClip("image2.jpg", mc2);
mcl.loadClip("image3.jpg", mc3);
mcl.loadClip("image4.jpg", mc4);
mcl.loadClip("image5.jpg", mc5);

Ceci lance le chargement de 5 images dans 5 MovieClips différents. Les 5 chargements se font en parallèle: la connexion au réseau internet est occupée par les arrivées successives et alternées des données des 5 images. C'est donc un petit abus de langage de dire qu'un MovieClipLoader permet le téléchargement des 5 images simultanément. Il faudrait plutôt parler de téléchargement “entrecroisé”. Si on suivait la progression du téléchargement de chaque image par des barres de progression, on verrait bien celles-ci avancer en même temps, mais au final le temps de téléchargement des 5 images serait bien supérieur à celui d'une seule image.

Dans notre diaporama, quand l'utilisateur demande à voir une image non chargée, nous pourrions penser à appeler loadClip pour demander le chargement de cette image. Ce chargement se cumulerait alors avec le chargement en cours.

Dans l'exemple que nous avons pris, pour demander à voir la cinquième image, l'utilisateur aura dû cliquer 4 fois sur le bouton image suivante. Cela revient à demander d'afficher la deuxième image puis, sans attendre qu'elle s'affiche, à demander la troisième image, puis sans attendre à demander la quatrième, puis la cinquième. Si à chaque fois nous appelons loadClip, il y aura 4 images qui se téléchargeront simultanément: la deuxième, la troisième, la quatrième et la cinquième. Ceci va ralentir beaucoup l'apparition de la cinquième image, ce qui n'est pas ce que nous voulons.

C'est pour cela que nous avons besoin d'une méthode qui nous permette d'arrêter le chargement en cours avant de lancer celui de l'image demandée.

2- La méthode MovieClipLoader.unloadClip()

C'est tout simple: pour arrêter un chargement en cours, il suffit d'appeler la méthode unloadClip, qui supprime un MovieClip chargé par la méthode loadClip.

// Demander le chargement:
var mcl:MovieClipLoader = new MovieClipLoader;
mcl.loadClip("image1.jpg", mc);
 
// Plus tard dans le code, demander la suppression du MovieClip chargé:
mcl.unloadClip(mc);

Cette méthode fonctionne également pour un MovieClip en cours de chargement, et c'est elle que nous allons utiliser.

3- Interrompre le chargement en cours pour lancer un autre chargement

Ecrivons une fonction chargerImage qui lance le chargement de l'image dont on lui passe le numéro en paramètre, et qui interrompt le chargement qui était en cours. Renommons la fonction chargerImageSuivante que nous avions, et modifions-la ainsi:

function chargerImage(iImage:Number) {
	if (loadingImage == iImage) return;
	if (loadingImage != undefined && imagesMC[loadingImage].isLoaded == undefined) {
		mcl.unloadClip(imagesMC[loadingImage]);
	}
	loadingImage = iImage;
	mcl.loadClip("images/image" + loadingImage + ".jpg", imagesMC[loadingImage]);
}

Appelons cette fonction pour charger la première image en remplaçant

var loadingImage:Number = 0;
mcl.loadClip("images/image0.jpg", imagesMC[0]);

par:

var loadingImage:Number;
chargerImage(0);

Le code correspondant se trouve également en pièce jointe: 3)

4- Explications

Examinons le code de la fonction chargerImage:

if (loadingImage == iImage) return;

Nous ne savons pas encore à quels moments nous appellerons la fonction. Nous pouvons imaginer qu'on en vienne à l'appeler pour demander le chargement de l'image qui est déjà en train de se charger. Dans ce cas il serait dommage que la fonction interrompe le chargement pour le relancer aussitôt. D'où cette première ligne qui met fin à la fonction si l'image qu'on demande à charger était déjà en train de le faire.

C'est une bonne habitude de programmation que de prévoir tous les cas possibles lors de l'écriture d'une fonction, même si on ne sait pas si ces cas se présenteront jamais. Ceci peut éviter du temps passé à déboguer le programme.

Ensuite, nous devons interrompre le chargement de l'image qui était en train de se charger, s'il y a lieu. Car nous ne sommes pas sûr qu'il y ait un chargement à interrompre lors de l'appel de la fonction chargerImage. Là aussi nous allons prévoir tous les cas de figure, et vérifier ces deux conditions pour être sûr qu'il y a bien un chargement a interrompre:

  • Il faut qu'il y ait déjà eu au moins un appel à cette fonction, ce qui peut se vérifier par la variable loadingImage qui aura la valeur undefined lors du premier appel de la fonction.
  • Il faut que le dernier chargement ne soit pas terminé, ce qui se vérifie par la propriété isLoaded du MovieClip correspondant.

unloadClip doit donc s'exécuter si une première condition est vraie et si une deuxième condition est vraie. Nous allons pour cela utiliser l'instruction if, et utiliser l'opérateur logique && qui signifie et (and en anglais):

if (loadingImage != undefined && imagesMC[loadingImage].isLoaded == undefined) ...

Ce qui se lit:
Si (loadingImage != undefined) est vraie et si (imagesMC[loadingImage].isLoaded == undefined est vraie) alors
Autrement dit:
Si (loadingImage est définie) et si (imagesMC[loadingImage].isLoaded est indéfinie) alors … Ou encore:
Si (une image se charge) et si (cette image n'a pas fini de se charger) alors

Ce qui introduit bien les deux conditions dont nous avons besoin pour être sûrs qu'il y a un chargement à interrompre. Dans ce cas, et seulement dans ce cas, la méthode unloadClip est appelée pour interrompre le chargement du MovieClip en cours de chargement.

Les deux dernières lignes de la fonction mémorisent l'index de la nouvelle image en cours de chargement et lancent ce chargement.

5- Demander à charger l'image que l'utilisateur désire voir

Nous pouvons maintenant modifier la fonction afficherImageActuelle pour qu'elle demande à charger l'image désirée si elle ne l'est pas encore, et qu'elle fasse alors apparaître la barre de progression 4):

function afficherImageActuelle() {
	progressMC._visible = false;
	if (imagesMC[imageActuelle].isLoaded) startFondu(imagesMC[imageActuelle]);
	else {
		chargerImage(imageActuelle);
		afficherProgressBar();
	}
}

Remarque: On pourrait se dire qu'il est dommage d'annuler le chargement d'une image dans le cas où celui-ci est bien avancé. Mais n'oublions pas que même si le chargement est annulé, les données déjà reçues sont dans le cache du navigateur. Quand par la suite on demandera de nouveau à charger cette image, ce sera comme si on reprenait le chargement là où il s'était arrêté.


II- Déterminer la prochaine image à charger

Quand le chargement d'une image était terminé, la fonction onLoadInit demandait jusque-là le chargement de l'image suivante. Ceci n'est plus valide car le fait de charger en priorité l'image que demande à voir l'utilisateur et d'interrompre des chargements peut amener à une situation où l'image suivante est déjà chargée, mais où il reste des images à charger. On peut se retrouver avec une situation aussi complexe que, pour un album de 8 images:

image 0 chargée,
image 1 non chargée,
images 2, 3 et 4 chargées,
image 5 non chargée,
images 6 et 7 chargées,
l'image 3 vient de terminer son chargement (loadingImage vaut 3) et s'affiche (imageActuelle vaut 3).

Comment allons-nous choisir la prochaine image à charger?

Nous allons décider de choisir la première image non chargée en partant du début. Dans l'exemple ce serait l'image 1 (la deuxième, donc) qu'il faudrait charger.

Nous allons essayer de trouver une manière de faire cela. Face à un problème de programmation, il est parfois utile d'essayer d'isoler le problème de son contexte pour trouver une méthode adéquate. C'est souvent plus simple.


III - Un exercice d'algorithmique

1- Enoncé du problème

Pour isoler notre problème, créons un nouveau programme qui commence par:

var a:Array = new Array();
a[0] = true;
a[1] = false;
a[2] = true;
a[3] = true;
a[4] = true;
a[5] = false;
a[6] = true;
a[7] = true;

Et cherchons un algorithme qui permette de trouver le premier élément d'un tableau correspondant à une condition donnée. Ici, essayons d'écrire un code qui trouve le premier élément du tableau a qui vaut false.

Comme vous le voyez, j'en profite pour introduire le terme d'algorithme, qui ne veut rien dire d'autre que “la suite d’opérations dans un langage bien défini permettant de résoudre par calcul un problème”. Le mot peut sembler savant, mais ce n'est rien d'autre que faire ce que nous faisons depuis le début de cette série de tutoriaux :-D . (Pour en savoir plus sur le terme “algorithme”, voici un article de wikipedia).

Il est possible de résoudre le problème avec la boucle for, que nous avons déjà utilisée (voir cet article). Pouvez-vous essayer d'écrire le code qui trouve le premier élément false du tableau a, mémorise son index dans une variable nommée firstFalse, et l'affiche dans la fenêtre de sortie?

Je vous laisse chercher, prenez votre temps, c'est là qu'on apprend le plus…

Comme toujours dans ces cas là, il y a plusieurs solutions:

2- Première solution, heu, non, première erreur

var firstFalse:Number;
for (var i:Number = 0; i < 8; i++) {
	if (!a[i]) firstFalse = i;
}
trace("Le premier élément false est au rang " + firstFalse);

Grâce à un boucle for et à une variable i, on parcourt le tableau en partant du premier élément jusqu'à son dernier élément. Si (!a[i] est vrai), c'est-à-dire Si (a[i] est faux), alors on mémorise i comme étant l'index de l'élément recherché.

C'est une erreur. Effectivement, quand i vaudra 1, a[1] valant false, firstFalse prendra bien la valeur 1. Mais par la suite i prendra la valeur 5, et comme a[5] est également false, firstFalse prendra la valeur 5. A la fin de la boucle, on aura donc firstFalse qui vaut 5, ce qui est l'index du dernier élément du tableau qui vaut false, et non pas le premier.

3- Première vraie solution

Pour éviter que firstFalse soit modifié alors qu'il a déjà pris une valeur, nous pouvons faire:

var firstFalse:Number;
for (var i:Number = 0; i < 8; i++) {
	// On teste si l'élément est false, et on mémorise son index
	// uniquement si c'est la première fois que ça arrive:
	if (!a[i] && firstFalse == undefined) firstFalse = i;
}
trace("Le premier élément false est au rang " + firstFalse);

Pour i valant 1, a[i] est faux et firstFalse est undefined, donc firstFalse prend la valeur 1.
Pour i valant 5, a[i] est faux mais firstFalse n'est pas undefined donc firstFalse=i n'est pas exécuté et firstFalse garde la valeur 1. C'est bien l'indice du premier élément faux du tableau a.

4- Deuxième solution

Une autre façon de faire serait:

var firstFalse:Number;
// On parcourt le tableau en partant de la fin
for (var i:Number = 7; i >= 0; i--) {
	if (!a[i]) firstFalse = i;
}
trace("Le premier élément false est au rang " + firstFalse);

Comme le tableau est parcouru en partant de la fin et en remontant vers le début, grâce à i–, le dernier élément false rencontré sera le plus proche du début du tableau. firstFalse aura bien pour valeur l'index du premier élément false du tableau.

5- Troisième solution

Une solution que vous n'auriez pu trouver, à moins d'avoir déjà découvert l'existence de l'instruction break, qui permet d'interrompre une boucle:

var firstFalse:Number;
for (var i:Number = 0; i < 8; i++) {
	if (!a[i]) {
		firstFalse = i;
		break; // Arrête la boucle dès qu'un false a été trouvé
	}
}
trace("Le premier élément false est au rang " + firstFalse);

Pour i valant 1, a[i] est faux, donc firstFalse prend la valeur 1. Puis l'instruction break demande l'interruption de la boucle, qui ne sera donc pas exécutée pour les valeurs 2, 3, 4, 5, 6, 7. firstFalse gardera donc la valeur 1.

6- Bilan

Chaque méthode a ses avantages et inconvénients:

  • La première a une condition plus lourde pour le if, mais n'exécute l'instruction d'affectation firstFalse=i qu'une fois.
  • La deuxième est la plus compacte avec une condition plus simple que la première, mais exécute l'instruction d'affectation autant de fois qu'il y a de false dans le tableau.
  • La troisième utilise l'instruction break qui n'est pas très élégante, un peu comme si on disait “fait cela 8 fois” puis “non non arrête tout!”. Son grand avantage est que la boucle ne s'exécute pas obligatoirement 8 fois, comme pour les autres solutions, mais s'arrête au premier false rencontré.

Imaginons que le tableau fasse 1000 éléments et que le premier false soit en 3ième position, ce serait quand même dommage de tester les 997 éléments restant pour rien, ce qui va prendre du temps inutile. La troisième solution emporte donc la palme de l'efficacité.

Nous pouvons donc répondre à la question posée au paragraphe II. En testant la propriété isLoaded des MovieClips du tableau imagesMC, le code suivant afficherait le numéro de la première image non chargée:

var nextImageToLoad:Number;	// Index de la prochaine image a charger.
for (var iImage:Number = 0; iImage < nbrImages; iImage++) {
	if (imagesMC[iImage].isLoaded == undefined) {
		nextImageToLoad = iImage;
		break;
	}
}
if (nextImageToLoad != undefined) trace("La première image à charger est l'image de rang " + nextImageToLoad);
else trace("Toutes les images sont déjà chargées");

Nous avons donc trouvé un premier algorithme qui marche. Ouf. Mais l'usage de l'instruction break aurait pu être évitée par une façon plus adaptée de coder la même chose, en utilisant un nouveau type de boucle que nous n'avons pas encore présenté:


IV- La boucle while

Nous avons introduit ici le terme de boucle, et l'instruction for. Voici maintenant une nouvelle façon de réaliser une boucle:

1- Présentation

while (condition) instruction;

La boucle while (tant que en français) permet d'exécuter l'instruction en boucle tant que la condition est vraie. L'instruction peut être bien sûr un bloc d'instruction entre accolades.

Quand flash arrive à une telle ligne, il évalue la condition. Si le résultat est vrai, il exécute l'instruction. Aussitôt après, il teste de nouveau la condition. Si le résultat est vrai il exécute à nouveau l'instruction. Et ainsi de suite. L'instruction va donc s'exécuter en boucle tant que la condition est vraie.

Comme la boucle ne s'arrêtera que si la condition devient fausse, il faut impérativement que l'instruction ou le bloc d'instruction modifie cette condition, sinon on se retrouve avec une boucle infinie.

2- Exemple

var i:Number = 0;
while (i < 10) {
	trace(i);
	i++ ;
}

Ceci va afficher les nombres de 0 à 9.

Explication:
On commence par initialiser une variable i à la valeur 0. Comme (i<10) est vraie, le bloc d'instruction s'exécute: 0 s'affiche et i augmente de 1, et passe donc à la valeur 1. (i<10) est encore vrai, le bloc d'instruction s'exécute de nouveau, 1 est affiché, et i passe à la valeur 2, etc jusqu'à ce que i prenne la valeur 10. Alors (i<10) est faux et l'exécution de la boucle s'arrête.

Nous aurions pu faire la même chose avec une boucle for, qui existe justement pour ce cas de figure.

3- Autre exemple

var i:Number = 2;
while (i < 1000) {
	trace(i);
	i = i * i;
}

Ceci va afficher 2, 4, 16, 256 dans la fenêtre de sortie.

4- Exemple à ne pas suivre

var i:Number = 0;
while (i < 10) {
	trace(i);
}

Ceci oublie de modifier i dans le bloc d'instruction, et entraîne une boucle infinie (si vous l'exécutez, attendez un moment, votre ordinateur va vous proposer d'interrompre l'exécution du script, surtout répondez “oui”).

5- Applications

Pouvez-vous maintenant essayer de refaire l'exercice d'algorithmique avec une boucle while?

Solution:

var i:Number = 0;
while (i < 8 && a[i]) i++;
if (i == 8) trace("Tous les éléments sont true.");
else trace("Le premier élément false est au rang " + i);

La boucle augmente i de 1 à chaque tour, et s'arrête quand i vaut 8 ou que l'élément de rang i est false.

Si i a atteint la valeur 8, c'est qu'aucun élément du tableau n'avait pour valeur false. Dans le cas contraire, i a pour valeur l'index du premier élément du tableau qui a pour valeur false.

De même, nous pouvons utiliser la boucle while pour trouver la première image à charger:

var iImage:Number = 0;
while (iImage < nbrImages && imagesMC[iImage].isLoaded) iImage++;
if (iImage < nbrImages) trace("La première image à charger est l'image de rang " + iImage);
else trace("Toutes les images sont déjà chargées");


V- La fonction findNextImageToLoad

Nous avons maintenant tout ce qu'il nous faut pour déterminer quelle est la prochaine image à charger.

1- Valeur de retour d'une fonction

Nous allons écrire une fonction findNextImageToLoad qui se chargera de trouver la prochaine image à charger. Pour l'instant, les fonctions que nous avons écrite “faisaient” quelque chose (voir ici pour rappel), mais ne renvoyaient pas de résultat. Ici nous voudrions pouvoir écrire:

var imageToLoad:Number = findNextImageToLoad();

Cette fonction doit donc renvoyer un résultat, de la même manière que d'autres que nous avons déjà utilisées, comme getNextHighestDepth qui renvoie un nombre (voir ici), ou encore createEmptyMovieClip qui renvoie une référence au MovieClip créé (voir ici).

Pour déclarer une telle fonction on écrit:

function maFonction(paramètres):type {
	calculs...
	return résultat;
}

La seule différence par rapport aux fonctions que nous avons déjà écrites sont:

  • Ajouter la valeur à renvoyer après l'instruction return,
  • Déclarer le type de la valeur renvoyée (Number, Boolean, Array, MovieClip, …) dans l'en-tête de la fonction, après la liste des paramètres. Comme pour la déclaration des variables, spécifier le type de la valeur de retour d'une fonction est facultatif. Pour la même raison, je conseille de le faire le plus souvent possible.

2- La fonction

Si nous transformons l'algorithme obtenu à la fin de la section précédente pour en faire une fonction, nous obtenons:

function findNextImageToLoad():Number {
	var iImage:Number = 0;
	while (iImage < nbrImages && imagesMC[iImage].isLoaded) iImage++ ;
	if (iImage == nbrImages) return undefined;
	else return iImage;
}

Cette fonction renvoie l'index de la première image non chargée, ou undefined si elles le sont toutes.

3- Utilisons notre nouvelle fonction

Nous pouvons maintenant utiliser cette fonction.

Modifions onLoadInit, qui va utiliser cette fonction et la fonction chargerImage pour lancer le chargement d'une image à la fin du chargement d'une autre:

mclListener.onLoadInit = function (mc:MovieClip) {
	mc._width = 400;
	mc._height = 300;
	mc._visible = false;
	mc.isLoaded = true;
	if (mc == imagesMC[imageActuelle]) {
		progressMC._visible = false;
		startFondu(imagesMC[imageActuelle]);
	}
	var nextImageToLoad:Number = findNextImageToLoad();
	if (nextImageToLoad != undefined) chargerImage(nextImageToLoad);
}

Nous pouvons exécuter ce nouveau diaporama 5):

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

Il marche! Si l'utilisateur demande à voir une image qui n'est pas encore téléchargée, celle-ci commence à se charger immédiatement 6). Pour vérifier qu'après qu'une image soit chargée, c'est bien la première image non chargée (en partant du début) qui se charge, on peut faire la manipulation suivante:

- Laisser se charger et apparaître la première image.
- Aller à la troisième image en pressant le bouton image suivante deux fois de suite.
- La deuxième image n'a donc pas eu le temps de se charger, et on voit s'afficher la barre de progression du chargement de la troisième image.
- Laisser la troisième image apparaître. A ce moment-là, la fonction findNextImageToLoad doit être appelée pour déterminer le numéro de la prochaine image à charger. Elle doit normalement trouver que la deuxième image est la première image de l'album qui n'est pas chargée. Le préchargement de cette image a donc déjà dû commencer.
- Effectivement, si on presse le bouton image précédente sans trop attendre, on tombe sur la barre de progression du chargement de la deuxième image, qui est déjà avancée, signe que le préchargement avait bien commencé. Si à la place on presse le bouton image suivante, on tombe sur la barre de progression du chargement de la quatrième image. Cette barre commence à zéro, nous confirmant que le préchargement de cette image n'avait pas commencé, puisque c'était celui de la deuxième qui était en cours.

Tout ce travail porte ses fruits, heureusement (!), et nous avons là une version du diaporama qui fait en sorte de faire patienter l'utilisateur le moins possible pour consulter les images.


VI- Dernier réglage

Nous avons déjà consacré beaucoup de temps à ce problème du préchargement. Le dernier résultat pourrait nous contenter. Mais… une autre idée ne vous est-elle pas venue à l'esprit?

La fonction findNextImageToLoad renvoie le numéro de la première image non chargée en partant du début. Mais si l'utilisateur a choisi de voir l'image 25 (par exemple), pouvons-nous faire des hypothèses sur la prochaine image qu'il désirera voir?

Comme dernière amélioration, nous allons estimer que si l'utilisateur affiche une image, l'image la plus probable qu'il demandera ensuite à afficher est l'image suivante, et que la seconde image la plus probable sera celle qui précède. Nous allons donc modifier findNextImageToLoad pour qu'elle renvoie en priorité l'une de ces deux images. Si ces deux images sont déjà chargées, elle cherchera la première image non chargée à partir de l'image actuellement affichée. Si toutes les images qui suivent sont chargées, alors elle cherchera la première image non chargée avant l'image actuelle.

function findNextImageToLoad():Number {
	// 1- Vérification de l'image suivante
	var nextImage:Number = imageActuelle + 1;
	if (nextImage == nbrImages) nextImage = 0;
	if (!imagesMC[nextImage].isLoaded) return nextImage;
	// 2- Vérification de l'image précédente
	var previousImage:Number = imageActuelle - 1;
	if (previousImage == -1) previousImage = nbrImages - 1;
	if (!imagesMC[previousImage].isLoaded) return previousImage;
	// 3- Vérification de toutes les images suivantes
	var iImage:Number = imageActuelle + 2;
	while (iImage < nbrImages && imagesMC[iImage].isLoaded) iImage++ ;
	if (iImage < nbrImages) return iImage;
	// 4- Vérification de toutes les images précédentes
	iImage = imageActuelle - 2;
	while (iImage >= 0  && imagesMC[iImage].isLoaded) iImage-- ;
	if (iImage >= 0) return iImage;
	// 5- Toutes les images sont chargées
	return undefined;
}

La fonction a pris du volume mais devrait vous rester compréhensible:

  1. Elle calcule d'abord l'index de l'image suivant celle qui est affichée, en tenant compte du fait qu'on pouvait en être à la dernière image. Si cette image n'est pas chargée elle renvoie son numéro et la fonction s'arrête là, sinon:
  2. Elle calcule l'index de l'image précédente, en tenant compte du fait qu'on pouvait en être à la première image. Si cette image n'est pas chargée elle renvoie son numéro et la fonction s'arrête là, sinon:
  3. Elle parcours toutes les images suivantes, sans tenir compte de celle qui suit immédiatement (puisque déjà vérifiée en premier), à partir du rang imageActuelle+2. Si elle trouve une image non chargée elle en renvoie le numéro et s'arrête là. Notons que si on en était à la dernière ou à l'avant-dernière image, il n'y a pas d'image d'index imageActuelle+2 et la boucle while n'est pas même exécutée une fois.
  4. Elle parcours toutes les images précédente, sans tenir compte de celle qui précède immédiatement (puisque déjà vérifiée), à partir du rang imageActuelle-2 et en allant vers 0. Si elle trouve une image non chargée elle en renvoie le numéro et s'arrête là. Si on en était à l'image 0 ou à l'image 1, il n'y a pas d'image d'index imageActuelle-2 et la boucle while n'est pas même exécutée une fois.
  5. Si cette partie du code est atteinte c'est que toutes les images sont chargées, la fonction renvoie undefined.

Et voilà 7):

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

Cette fois, c'est terminé!


Conclusion

Le préchargement des images est enfin mis en place. De nombreuses notions de programmation ont été introduites à cette occasion. Si vous êtes débutant, vous avez (j'espère!) appris beaucoup. Merci à vous de faire vos commentaires sur ce tutoriel, qui peut sûrement être amélioré. Y a-t-il des points que vous avez trouvé difficiles? Avez-vous encore des questions ou des zones de flou sur comment le programme marche? Vos réflexions sont les bienvenues sur le forum en réponse au message concernant ce tutoriel. Vous pouvez également ouvrir un nouveau sujet.

Il nous reste encore à mettre en place une fonction de défilement automatique des images, et bien sûr les fameuses miniatures. Nous nous y attèlerons dans les prochains articles.


Pour en savoir plus

Pour avoir des précisions ou des renseignements complémentaires, vous pouvez consulter 8):

  • Au sujet de MovieClipLoader et unloadClip:
    • Aide de Flash > Référence du langage ActionScript 2.0 > Classes ActionScript > MovieClipLoader.
    • Aide de Flash > Référence du langage ActionScript 2.0 > Classes ActionScript > MovieClipLoader > unloadClip.
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Utilisation des images, du son et de la vidéo > Chargement de fichiers SWF et de fichiers d'images externes.
    • La section Charger du contenu : images, animations, classes du wiki. Plusieurs bons tutoriaux.
  • Au sujet des conditions et de l'opérateur && :
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Eléments fondamentaux du langage et de la syntaxe > Présentation des opérateurs > Présentation des opérateurs logiques.
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Eléments fondamentaux du langage et de la syntaxe > Présentation des instructions > Présentation des conditions.
    • Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > opérateurs > &&, opérateur (AND logique).
    • Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > Instructions > Instruction if.
  • Au sujet de la boucle while:
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Eléments fondamentaux du langage et de la syntaxe > Présentation des instructions > Répétition d'actions à l'aide de boucles > Utilisation des boucles while.
    • Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > Instructions > Instruction while.
    • Cet article du site du zéro.
  • Au sujet des fonctions et de leur valeur de retour:
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Fonctions et méthodes > Présentation des fonctions et des méthodes > Renvoi de valeurs depuis les fonctions.
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Fonctions et méthodes > Présentation des fonctions et des méthodes.
    • Cet article du site du zéro.


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

1) , 3) , 4) , 5) , 7) Vous pouvez télécharger les fichiers de code correspondants à cet article et les swf compilés, 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
2) , 6) Au moment où vous regardez un swf inclus dans cette page, le préchargement des images est peut-être déjà terminé. Si vous désirez voir son comportement pendant le préchargement, rechargez la page, ce qui relancera le préchargement des images.
8) 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).