Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Créer un diaporama pas à pas - 8 - Boutons, interrupteur et défilement automatique des images - setInterval, clearInterval

Compatible ActionScript 2. Cliquer pour en savoir plus sur les compatibilités.Par lilive (Olivier Tarasse), le 06 septembre 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 aux fidèles acharnés qui suivent la réalisation du diaporama, ils savent que nous avons, lors de la partie précédente, et au prix d'admirables efforts, mis en place un système de préchargement digne de ce nom. Nous allons maintenant souffler un peu avec la mise en place d'une fonction de défilement automatique des images et en enjolivant les boutons de l'interface, ce qui fait toujours plaisir. Nous allons notamment confectionner un bouton interrupteur play/pause qui changera d'aspect selon que le défilement des images est ou non activé.

Sans plus attendre, voici ce que nous aurons obtenu à la fin de cet article:

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


I - Fabriquer des boutons animés

Avec Flash il est très simple d'avoir des boutons qui réagissent au passage et au clic de la souris. Le comportement typique d'un bouton est de changer légèrement d'apparence quand le pointeur de la souris le survole, attirant ainsi l'attention de l'utilisateur sur le fait qu'il y a ici “quelque chose à faire”, en l'occurrence: cliquer. De même, un bouton change très souvent d'apparence au moment où l'utilisateur clique dessus, le temps qu'il tient le bouton de sa souris enfoncé, ce qui est comme une confirmation visuelle que le bouton “reçoit bien le clic”.

Voici un tel bouton:

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

Comme il est bien plus agréable d'avoir des boutons animés, que ce n'est pas difficile à mettre en place, et que j'y arrive tard dans cette série de tutoriaux, vous vous en êtes peut-être déjà occupé vous-même. Si c'est le cas vous pouvez passer immédiatement au chapitre II. Pour les autres, nous allons tout d'abord voir comment on place un bouton sur la scène:

1- Placer un bouton sur la scène avec l'IDE de flash

Pour ceux qui utilisent l'IDE (Integrated Development Environment - Environnement de Développement Intégré) de Flash, je ne vais pas détailler la façon de faire car cela a déjà été fait de nombreuses fois ailleurs. Il y a bien sûr:

  • Aide de flash > Utilisation de Flash > Utilisation de symboles, d'occurrences et d'actifs de bibliothèque > Utilisation des symboles de bouton > Création d'un bouton.

Et une simple recherche sur le net avec les mots “flash créer bouton” donne de nombreuses réponses, par exemple:

2- Placer un bouton sur la scène avec swfmill

Par contre, pour ceux qui n'utilisent pas flash IDE mais le duo mtasc/swfmill, on trouve moins facilement de documentation sur la façon de créer un bouton. swfmill est, je le rappelle, un outil de développement libre permettant de générer des swf. Utilisé de concert avec mtasc on peut compiler des swf sans l'IDE de Flash.

Voici le fichier XML qui permet de créer un bouton nommé btn sur la scène, en utilisant 3 fichiers d'images pour avoir les 3 différents états du bouton 1):

<?xml version="1.0" encoding="utf-8" ?>
<movie version="8" width="400" height="70" framerate="25">
	<background color="#555555"/>
	<frame>
		<clip id="nextBtnUp" import="boutons/nextBtnUp.png"/>
		<clip id="nextBtnOver" import="boutons/nextBtnOver.png"/>
		<clip id="nextBtnDown" import="boutons/nextBtnDown.png"/>
 
		<library>
			<clip id="nextBtn">
				<frame name="_up">  
					<place id="nextBtnUp" depth="1" />
					<stop />
				</frame>
				<frame name="_over">
					<place id="nextBtnOver" depth="2" />
					<stop />
				</frame>
				<frame name="_down">
					<place id="nextBtnDown" depth="3" />
					<stop />
				</frame>
			</clip>
		</library>
 
		<place id="nextBtn" name="btn" x="10" y="10" depth="0"/>
	</frame>
</movie>

Les 3 états graphiques du bouton sont respectivement les frames “_up”, “_over” et “_down” correspondant aux états “au repos”, “survolé” et “abaissé”.

Notez que le bouton ne s'animera au passage du pointeur de la souris que si au moins une de ses méthodes de gestionnaire d'événement (onRollOver, onRollOut, onPress, onRelease, onReleaseOutside) est définie, ce que nous allons faire maintenant:

3- Associer du code au bouton

Créez un nouveau document, et placez un nouveau bouton nommé btn sur la scène (si vous utilisez Flash IDE, il faut donner btn comme nom d'occurrence du bouton, dans la fenêtre des propriétés du bouton). Il ne reste plus qu'à lui associer du code Action Script, pour que le bouton soit vraiment interactif.

Pour cela, il convient de définir les méthodes de gestionnaire d'évènement du bouton. Pour cela, on fait la même chose que pour associer du code aux évènements d'un MovieClip, comme nous l'avons déjà vu en deuxième partie. La seule chose qui change est que nous avons maintenant un objet Button à la place d'un objet MovieClip. Placez ce code sur la première image du scénario principal (pas du bouton, attention):

trace("Approchez le pointeur de la souris du bouton...");
 
var btn:Button = this["btn"];
 
btn.onRollOver = function () {
	trace("Evènement onRollOver:");
	trace("Le pointeur vient d'arriver au-dessus du bouton.");
}
btn.onRollOut = function () {
	trace("Evènement onRollOut:");
	trace("Le pointeur vient de quitter le bouton.");
}
btn.onPress = function () {
	trace("Evènement onPress:");
	trace("Le bouton vient d'être pressé.");
}
btn.onRelease = function () {
	trace("Evènement onRelease:");
	trace("Le bouton vient d'être relâché.");
}
btn.onReleaseOutside = function () {
	trace("Evènement onReleaseOutside:");
	trace("Le bouton vient d'être relâché,");
	trace("le pointeur de la souris était en dehors du bouton à ce moment.");
}

Exécutez ce programme. Vous devriez obtenir les messages correspondant aux évènements dans la fenêtre de sortie 2).

Si nous utilisons un champ de texte pour visualiser les sorties plutôt que trace, nous obtenons ceci:

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

Ce qui correspond au code:

var message:TextField = this.createTextField("message", this.getNextHighestDepth(), 40, 10, 100, 20);
message.textColor = 0xffffff;
message.autoSize = "left";
message.text = "Approchez le pointeur de la souris du bouton...";
 
var btn:Button = this["btn"];
 
btn.onRollOver = function () {
	message.text = "Evènement onRollOver:\nLe pointeur vient d'arriver au-dessus du bouton.";
}
btn.onRollOut = function () {
	message.text = "Evènement onRollOut:\nLe pointeur vient de quitter le bouton.";
}
btn.onPress = function () {
	message.text = "Evènement onPress:\nLe bouton vient d'être pressé.";
}
btn.onRelease = function () {
	message.text = "Evènement onRelease:\nLe bouton vient d'être relâché.";
}
btn.onReleaseOutside = function () {
	message.text = "Evènement onReleaseOutside:\n" +
		"Le bouton vient d'être relâché,\n" +
		"le pointeur de la souris était en dehors du bouton à ce moment.";
}

Pour un rappel sur l'utilisation des champs de texte TextField voir cette partie. La seule nouveauté à ce sujet est que pour obtenir un retour à la ligne à l'intérieur du texte, nous utilisons le caractère de retour à la ligne qui se note \n.

4- Retour au diaporama

Pour le diaporama, nous pouvons maintenant créer sur la scène de vrais boutons pour avoir les images suivantes et précédentes. Au niveau du code, la seule chose à modifier et de remplacer les MovieClip par des Button:

var nextBtn:Button = this["nextBtn"];
var lastBtn:Button = this["lastBtn"];

Le code intégral du diaporama est toujours en pièce jointe 3). Et cela donne les jolis boutons que voilà:

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

Notez un petit changement visuel par rapport aux versions précédentes, avec le rajout d'une barre horizontale dégradée qui accueillera par la suite d'autres éléments que les boutons.


II - Fabriquer un interrupteur

Nous aurions maintenant besoin d'avoir un bouton de type “interrupteur”, c'est-à-dire un bouton à deux positions: “marche” et “arrêt”. Nous utiliserons ce bouton pour lancer et arrêter le défilement automatique des images du diaporama. Ce bouton se présentera ainsi:

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

Vous voyez que ce bouton se comporte comme un bouton normal, jusqu'au moment où on clique dessus. Au moment où le bouton est relâché son apparence change, et devient celle d'un autre bouton. Pour confectionner un tel bouton interrupteur nous allons donc procéder très simplement, en créant deux boutons “normaux” l'un sur l'autre, et en n'affichant jamais qu'un seul des deux.

Créez un nouveau document. Placez sur scène deux boutons (voir I), l'un nommé playBtn et l'autre pauseBtn. Faites en sorte que ces boutons soient affichés au même endroit sur la scène (aux mêmes coordonnées x et y). Entrez alors ce code sur la première image du scénario principal 4):

var playBtn:Button = this["playBtn"];
var pauseBtn:Button = this["pauseBtn"];
 
pauseBtn._visible = false;
 
playBtn.onRelease = function () {
	playBtn._visible = false;
	pauseBtn._visible = true;
}
 
pauseBtn.onRelease = function () {
	playBtn._visible = true;
	pauseBtn._visible = false;
}

C'est aussi simple que cela. Exécutez le programme, vous devriez obtenir un interrupteur.

Nous commençons par cacher le bouton pauseBtn en définissant sa propriété _visible à false. De cette façon seul le bouton playBtn est affiché et peut interagir avec le curseur de la souris. L'interrupteur est alors dans son état “pause”, et propose de cliquer sur lui pour le faire basculer à l'état “marche”.

Quand le bouton est pressé puis relâché, la méthode de gestionnaire d'évènement onRelease de playBtn est appelée, ce qui fait disparaître ce bouton et apparaître pauseBtn. L'interrupteur passe alors à l'état “marche” et propose de cliquer sur lui pour le faire basculer à l'état “pause”.

Inversement, la méthode onRelease de pauseBtn cache ce bouton et affiche playBtn, ce qui redonne à l'interrupteur son aspect initial.

L'interrupteur fonctionne. Pour lui associer des actions, il suffit d'ajouter à la méthode onRelease de playBtn le code qui doit être exécuté quand l'utilisateur commute l'interrupteur sur “marche”, et à la méthode onRelease de pauseBtn le code qui doit s'exécuter quand il est commuté sur “arrêt”.

Il reste un dernier choix à faire: L'utilisateur peut presser le bouton et faire glisser le pointeur de la souris en dehors avant de le relâcher. Ceci déclenche l'évènement onReleaseOutside. Dans ce cas, on peut décider de commuter l'interrupteur comme s'il avait été normalement pressé, ou bien on peut ne rien faire. Pour que l'interrupteur commute également dans ce cas, il faut définir la méthode onReleaseOutside comme on a définit onRelease. La manière la plus simple de le faire est de coder:

playBtn.onRelease = playBtn.onReleaseOutside = function () {
	playBtn._visible = false;
	pauseBtn._visible = true;
}
 
pauseBtn.onRelease = pauseBtn.onReleaseOutside = function () {
	playBtn._visible = true;
	pauseBtn._visible = false;
}


III - Les fonctions setInterval et clearInterval

Nous allons maintenant nous pencher sur une fonction qui permet d'exécuter le même code à des intervalles de temps régulier: setInterval. Nous utiliserons plus tard cette fonction pour faire défiler régulièrement les images du diaporama.

1- Lancer une fonction avec setInterval

setInterval permet d'appeler une même fonction à intervalles de temps régulier. Pour cela nous avons besoin d'une fonction à exécuter. Créez une nouveau document et entrez:

function afficherTemps() {
	trace(getTimer());
}

getTimer est une fonction qui renvoie le nombre de millisecondes écoulées depuis le début de l'exécution du swf. La fonction afficherTemps provoque donc l'affichage de ce nombre dans la fenêtre de sortie.

Si nous voulons appeler afficherTemps toutes les secondes, il suffit d'ajouter:

setInterval(afficherTemps, 1000);

Vous pouvez exécuter le programme. Vous devriez voir le temps s'afficher à intervalle plus ou moins régulier, car setInterval n'est pas d'une précision absolue.

2- Arrêter l'exécution de la fonction

Pour mettre fin à l'appel régulier de afficherTemps. Il faut utiliser la fonction clearInterval. Pour cela, il faut cette fois garder dans une variable le nombre renvoyé au moment de l'appel de setInterval. Comme ceci:

var intervalID:Number = setInterval(afficherTemps, 1000);
 
// Plus tard, ceci arrêtera l'intervalle:
clearInterval(intervalID);

clearInterval prend comme paramètre le nombre qui “identifie” l'intervalle que nous voulons arrêter. En effet, il est possible de lancer simultanément l'appel de plusieurs fonctions à intervalles de temps réguliers, en appelant plusieurs fois setInterval avec des paramètres différents. Pour que clearInterval puisse savoir lequel de ces intervalles il faut arrêter, il faut mettre de côté l'identifiant renvoyé au moment de l'appel de setInterval. C'est le rôle de la variable intervalID.

Nous pourrions par exemple décider d'arrêter l'exécution de la fonction afficherTemps quand 10 secondes se sont écoulées:

function afficherTemps() {
	var temps:Number = getTimer(); // Récupère le temps passé
	if (temps < 10000) trace(temps); // Si moins de 10 secondes, afficher le temps
	else clearInterval(intervalID); // Si plus de 10 secondes, arrêter l'intervalle
}
setInterval(afficherTemps, 1000);

Au bout de 10 secondes, (temps < 10000) est faux, et clearInterval est exécuté.

3- Remarque

N'oublions pas que le meilleur choix pour exécuter une même fonction à la cadence de l'animation de l'animation reste d'utiliser onEnterFrame, que nous avons introduit ici.


IV - Le défilement automatique des images

Nous voici donc outillés pour permettre à l'utilisateur de faire défiler les images du diaporama automatiquement, en appuyant sur un bouton play/pause.

1- Un premier essai

Nous pouvons déjà simplement tester le défilement automatique des images en ajoutant une seule ligne de code à notre diaporama, en demandant à ce que la fonction afficherImageSuivante soit appelée toutes les 3 secondes 5) :

setInterval(afficherImageSuivante, 3000);

En exécutant ce nouveau programme l'image affichée change toute seule toutes les 3 secondes.
Simple, non?

Ceci était juste pour tester la méthode. En fait nous allons nous y prendre autrement, aussi effaçons dès maintenant cette ligne de code.

2- L'interrupteur play/pause

Créons maintenant un interrupteur play/pause comme nous avons appris à le faire au chapitre II, en nommant les 2 boutons nécessaires playBtn et pauseBtn. Puis ajoutons le code de l'interrupteur:

var playBtn:Button = this["playBtn"];
playBtn.onRelease = playBtn.onReleaseOutside = function () {
	playBtn._visible = false;
	pauseBtn._visible = true;
}
 
var pauseBtn:Button = this["pauseBtn"];
pauseBtn.onRelease = pauseBtn.onReleaseOutside = function () {
	playBtn._visible = true;
	pauseBtn._visible = false;
}
 
playBtn.onRelease();

Ceci crée un interrupteur qui réagit à la souris, et la dernière ligne playBtn.onRelease() demande à exécuter la méthode onRelease de playBtn, ce qui positionne l'interrupteur sur “marche”. Ainsi les images commenceront à défiler dès le chargement du diaporama. Vous pouvez tout aussi bien décider que vous ne le souhaitez pas et appeler à la place pauseBtn.onRelease();

On peut déjà exécuter ce programme pour vérifier que l'interrupteur fonctionne. Evidemment, cliquer dessus n'agit pas encore sur le défilement des images.

Il faut maintenant ajouter le code qui va déclencher et arrêter le défilement automatique lors des manipulations de l'interrupteur.

3- Marche / Arrêt du défilement automatique

Créons 2 fonctions qui vont nous servir à lancer ou arrêter l'exécution de afficherImageSuivante à intervalles réguliers.

var playInterval:Number;
 
function initPlayInterval() {
	playInterval = setInterval(afficherImageSuivante, 3000);
}
 
function clearPlayInterval() {
	clearInterval(playInterval);
}

Nous déclarons une nouvelle variable playInterval qui va servir à stocker le nombre identifiant de l'intervalle, comme vu au chapitre II-2 .

La fonction initPlayInterval demande à ce que afficherImageSuivante s'exécute toutes les 3 secondes.

La fonction clearPlayInterval annule l'exécution automatique de afficherImageSuivante.

4- Contrôle du défilement automatique des images par les boutons

Faisons maintenant en sorte que l'interrupteur lance et arrête le défilement des images:

var isPlayPressed:Boolean;
 
var playBtn:Button = this["playBtn"];
playBtn.onRelease = playBtn.onReleaseOutside = function () {
	initPlayInterval();
	isPlayPressed = true;
	playBtn._visible = false;
	pauseBtn._visible = true;
}
 
var pauseBtn:Button = this["pauseBtn"];
pauseBtn.onRelease = pauseBtn.onReleaseOutside = function () {
	clearPlayInterval();
	isPlayPressed = false;
	playBtn._visible = true;
	pauseBtn._visible = false;
}

Comme vous le voyez, nous demandons à l'interrupteur de mettre en route ou d'arrêter l'exécution régulière de afficherImageSuivante grâce aux deux fonctions initPlayInterval et clearPlayInterval.

Nous introduisons également une nouvelle variable isPlayPressed qui vaudra true si l'interrupteur est en marche, false sinon. Cette variable va nous servir par la suite.

Nous pouvons exécuter le diaporama, ce qui nous donne:

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

Penchons-nous maintenant sur le cas suivant. Que doit-il se passer si l'utilisateur clique sur le bouton “image suivante” ou le bouton “image précédente” alors que le défilement automatique est en cours? Actuellement, si cela se produit, les 2 actions se cumulent: Si le défilement automatique est en cours, que la deuxième image (par exemple) de l'album s'affiche, et que l'utilisateur clique sur le bouton “image suivante” deux secondes après cette apparition, la troisième image va s'afficher en réponse au clic, mais va rester affichée très peu de temps, car une seconde après le défilement automatique fera s'afficher la quatrième image. Ceci ne semble pas très pratique pour l'utilisateur.

On pourrait imaginer que dans ce cas, il serait mieux de laisser la troisième image affichée pendant trois secondes avant de passer à la quatrième.

On peut aussi imaginer une autre solution, qui a ma préférence, en considérant que si l'utilisateur clique sur le bouton “image suivante” ou “image précédente”, c'est qu'il souhaite reprendre la main sur le choix des images à afficher, et stopper le défilement automatique. Pour obtenir ce résultat modifions les méthodes onPress des deux boutons de cette façon:

nextBtn.onPress = function () {
	if (isPlayPressed) pauseBtn.onRelease();
	afficherImageSuivante();
}
 
lastBtn.onPress = function () {
	if (isPlayPressed) pauseBtn.onRelease();
	afficherImagePrecedente();
}

Quand un des boutons est pressé, si l'interrupteur est en position marche (c'est-à-dire si isPlayPressed est vraie), la méthode onRelease de pauseBtn est appelée, ce qui simule un clic de l'utilisateur sur l'interrupteur et arrête le défilement automatique.

Voici le résultat:

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

Nous sommes quasiment au bout de nos peines. Il nous reste un dernier cas de figure à envisager:

5- Suspendre le défilement automatique pendant les chargements

Que faire si une image n'est pas encore chargée au moment où le défilement automatique demande à l'afficher?

Dans ce cas, faisons en sorte que le défilement automatique soit suspendu. C'est-à-dire que si l'image doit se charger, nous arrêtons l'intervalle, affichons la barre de progression, puis relançons l'intervalle quand la photo apparaît.

Pour cela modifions les fonctions afficherImageActuelle et onLoadInit 6):

function afficherImageActuelle() {
	progressMC._visible = false;
	if (imagesMC[imageActuelle].isLoaded) {
		startFondu(imagesMC[imageActuelle]);
	} else {
		chargerImage(imageActuelle);
		afficherProgressBar();
		// Une nouvelle ligne ici:
		if (isPlayPressed) clearPlayInterval();
	}
}
 
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]);
		// Et une autre là:
		if (isPlayPressed) initPlayInterval();
	}
	var nextImageToLoad:Number = findNextImageToLoad();
	if (nextImageToLoad != undefined) chargerImage(nextImageToLoad);
}

Il nous suffit de tester si l'interrupteur est sur la position marche (isPlayPressed est-elle vraie?) pour savoir si on doit arrêter l'intervalle au moment d'afficher la barre de progression dans afficherImageActuelle, et si on doit le relancer dans onLoadInit.

Ce qui nous donne la version finale du diaporama pour cette partie du tutoriel:

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

N'est-ce pas merveilleux?

N'oubliez pas qu'au moment où vous regardez ce swf, si le préchargement des images est déjà terminé, vous pouvez le relancer en rechargeant la page dans votre navigateur.


Conclusion

Nous nous arrêterons là pour la fonction de défilement automatique des images. Comme toujours, si vous rencontrez des difficultés ou si vous avez des suggestions d'améliorations, vous pouvez répondre sur le forum au message concernant ce tutoriel, ou ouvrir un nouveau sujet.

Dans le prochain article nous ferons quelques améliorations au diaporama, histoire d'apprendre à manipuler encore mieux les champs de texte et les positions des MovieClips, avant de nous attaquer au dernier gros morceau: la création des vignettes.


Pour en savoir plus

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

  • Au sujet de la création des boutons:
  • Au sujet des boutons et des évènements:
    • Aide de Flash > Référence du langage ActionScript 2.0 > Classes ActionScript > Button
    • Aide de Flash > Formation à ActionScript 2.0 dans Adobe Flash > Gestion d'événements > Utilisation de méthodes de gestionnaire d'événement
  • Au sujet de setInterval et clearInterval
    • Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > Fonctions globales > Fonction setInterval.
    • Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > Fonctions globales > Fonction clearInterval.
    • Cet article sur guepard's techblog.
  • Au sujet de getTimer: Aide de Flash > Référence du langage ActionScript 2.0 > Eléments du langage ActionScript > Fonctions globales > Fonction getTimer.


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

1) , 2) , 3) , 4) , 5) , 6) 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
7) 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).