Ce matin, pendant que ma blonde dormait, j'ai fait un petit exercice pour créer un diaporama de photos simple en JavaScript, où les images défilent automatiquement. En moins d'une heure, j'ai réalisé deux versions, une utilisant des méthodes standards procédurales, et l'autre, que je présenterai demain, qui est plus orientée objet et qui introduit les fermetures. J'ai écrit ce code pour le plaisir, alors je ne prétends pas qu'il soit parfait et je ne serais certainement pas prêt à le mettre tel quel en production sans l'avoir préalablement paufiné. Comme tout ce que je présente ici, l'objectif est surtout de présenter le concept et de voir les applications possibles.
Pour atteindre mon but, j'ai utilisé la librairie Prototype pour simplifier les appels document.getElementById par $() et Script.aculo.us pour ajouter un effet de transition dans le chargement des images. Le reste est du JS pur. Je peux aussi dire que je l'ai testé uniquement sous Firefox 3 et Internet Explorer 7.
Pour commencer, j'ai défini un conteneur HTML pour la photo et un autre pour le compteur d'images qui apparaîtra au dessous. L'objectif est simplement de créer une boucle qui chargera alternativement les images d'une liste selon un intervalle régulier. La balise <img> servira à recevoir l'image en changeant dynamiquement son attribut source. Le compteur indiquera le numéro de l'image courante et le nombre d'images au total.
<p><img id="picture" src=""></p>On définit en JavaScript le chemin où se trouvent les images et une variable array liste tous les fichiers.
<span id="detail"></span>
var path = 'images/vacances/';On initialise des variables pour indiquer l'image courante (l'indice dans la liste), le nombre total de photos et le temps d'affichage de chacune d'elles.
var pics = new Array(
'001.jpg',
'002.jpg',
'003.jpg',
'004.jpg',
'005.jpg',
'006.jpg',
'007.jpg',
'008.jpg',
'009.jpg',
'010.jpg'
);
var currentPicture = 0;Au chargement de la page, je démarre le slideshow en utilisant la notation de Prototype. Ensuite, je charge la première photo en appelant la méthode LoadPicture.
var totalPictures = pics.length;
var showImageSeconds = 4;
document.observe('dom:loaded', startSlideShow );Dans le conteneur d'image <img>, on remplace la source par le chemin de la première image dans l'array. On met à jour le compteur avec les valeurs courantes en utilisant update() de Prototype, mais on aurait pu le faire aussi bien avec InnerHTML. On fait apparaître l'image avec l'effet Appear de Scriptaculous (qui est l'inverse de Fade) qui dure une seconde. On affiche ensuite l'image quelques secondes selon la variable définie plus haut.
function startSlideShow() {
LoadPicture();
}
function LoadPicture() {Pour afficher l'image un certain temps, j'appelle setTimeout qui me permet d'effectuer une pause avant de montrer la suivante. Lorsque le temps se sera écoulé, la fonction ChangePicture sera appelée.
$('picture').src = path + pics[currentPicture];
// compteur
$('detail').update( (currentPicture + 1) + ' / ' + totalPictures);
Effect.Appear('picture', { duration:1, from:0.0, to:1.0 });
Display(showImageSeconds);
}
function Display(sec) {Lors du changement de photo, on vérifie si l'indice est le dernier de la liste. Si c'est le cas, on revient au début pour afficher la première photo. Un petit effet la fait disparaître et comme on veut voir la transition correctement, on doit attendre une seconde. Le temps de l'effet est spécifié dans la propriété duration alors on fait coïncider l'appel de Wait() pour attendre que l'effet soit terminé avant de changer d'image.
setTimeout("ChangePicture()", sec * 1000);
}
function ChangePicture() {Lorsque l'effet est terminé, on charge la photo suivante.
currentPicture++;
// si c'est la dernière
if (currentPicture == totalPictures )
currentPicture = 0;
Effect.Fade('picture', { duration:1, from:1.0, to:0.0 });
Wait(1);
}
function Wait(sec) {En exécutant le code, on devrait voir les images défiler en boucle une à une. Le problème avec ce genre de code procédural, c'est que ça ne forme pas un tout, il n'y a pas d'unité qui relie les variables et fonctions entre elles. Demain, je présenterai une refonte du code en version orientée objet et j'expliquerai le concept des fermetures JavaScript (closures) pour pouvoir créer un objet Slideshow mieux structuré, plus facile à comprendre et à maintenir.
setTimeout("LoadPicture()", sec * 1000);
}