LP
IMApp

Scripts
Clients

Leçon 09

Leçon 09 : Les images et les délais

Contenu :

Cette leçon présente tout d'abord la manipulation d'images en Javascript, puis ensuite les fonctions de délais, qui ne sont pas directement liées aux images, mais qui sont souvent combinées ensemble.

Objectifs :

Etre capable d'effectuer les manipulations de base sur les images et de réaliser les classiques comme les diaporamas et les galeries. Connaitre les fonctions de délais et savoir les combiner avec les images pour effectuer des animations de base

Les images

L'élément HTML IMG permet d'afficher des images. L'image effective visible à l'écran est spécifiée via l'attribut src qui contient le chemin (sur le serveur) du fichier image. La propriété fondamentale de l'attribut src est que, dès qu'on change sa valeur, l'image à l'écran est remplacée par la nouvelle image, sans entraîner de réaffichage de la page HTML qui contient l'élément image en question. En associant ce changement de contenu d'image à certains évènements, on peut obtenir des effets graphiques intéressants. Par exemple, si on dispose du code HTML suivant :

<p>
  Choisissez une ville :
  <select id="ville">
    <option value="pretoria.jpg" selected>Pretoria</option>
    <option value="washington.jpg">Washington</option>
    <option value="hanoi.jpg">Hanoï</option>
    <option value="berlin.jpg">Berlin</option>
    <option value="canberra.jpg">Canberra</option>
  </select>
  <p>
    <p>
      Cliquez <span onclick="afficher('ville','image-ville');">ici</span> pour voir
      une image de cette ville !
    </p>
    <img id="image-ville" src="pretoria.jpg" />
  </p>         
</p>

on peut afficher dans l'élément image adéquat (l'élément d'identifiant capitale) une image de la capitale sélectionnée par l'utilisateur, avec le code JavaScript suivant :

function afficher(selectId, imageId) {
	var villeElt = document.querySelector( "#" + selectId );
	var optionElt = villeElt[ villeElt.selectedIndex ];
	var imgElt = document.querySelector( "#" + imageId );
	imgElt.src = optionElt.value;	
}

Dans l'exemple précédent, c'est à partir d'un évènement extérieur à l'élément SELECT (le clic sur l'élément SPAN) qu'on va changer l'attribut src de l'image d'identifiant image-ville. On peut changer l'image sur un évènement produit sur l'élément SELECT lui-même. Le code HTML devient:

	
<p>
  Choisissez un pays :
  <select id="pays" onchange="afficher('pays','image-pays');">
    <option value="afds.jpg" selected>Afrique du Sud</option>
    <option value="usa.jpg">Etats-Unis</option>
    <option value="vietnam.jpg">Vietnam</option>
    <option value="allemagne.jpg">Allemagne</option>
    <option value="australie.jpg">Australie</option>
  </select>
  <p>
    <img id="image-pays" src="afds.jpg" />
  </p>         
</p> 	

et le code JavaScript reste inchangé.

Les éléments HTML IMG acceptent l'évènement onclick, ce qui fait qu'une image peut être cliquable. Par exemple, le code HTML suivant :

<p>
  <p>
    Cliquez sur l'image d'un pays pour voir une vue de sa capitale
  </p>
  <div>
    <img class="miniature" src="afds.jpg" onclick="voir('pretoria.jpg');" />
    <img class="miniature" src="usa.jpg" onclick="voir('washington.jpg');" />
    <img class="miniature" src="vietnam.jpg" onclick="voir('hanoi.jpg');" />
    <img class="miniature" src="allemagne.jpg" onclick="voir('berlin.jpg');" />
    <img class="miniature" src="australie.jpg" onclick="voir('canberra.jpg');" />
  </div>
  <img id="capitale" src="pretoria.jpg" />
</p>	

permet de disposer d'images miniatures sur lesquelles on peut cliquer pour faire apparaître une autre image dans l'élément d'identifiant capitale. Voilà le code JavaScript associé :

function voir(source) {
	document.querySelector( "#capitale" ).src = source;
}

Les exemples précédents sont disponibles dans les fichiers exemple-1.html et exemple-1.js

Exercice 1

Complétez le fichier exo1.js de façon que le document HTML contenu dans le fichier exo1.html présente un diaporama simple à l'utilisateur. En cliquant sur (l'image de) la flèche de droite, on affiche l'image suivante, et en cliquant sur (l'image de) la flèche de gauche, on affiche l'image précédente. Cet affichage est circulaire : autrement dit quand on a affiché la dernière image et qu'on demande à afficher la suivante, on affiche la première image, et quand on a affiché la première image et qu'on demande à afficher la précédente, on affiche la dernière image. Les images utilisées sont dans l'archive exo1.zip.

Fichier(s)

exo1.html , exo1.js , exo1.zip , exo10.zip

Exercice 2

Reprenez l'exercice précédent, mais cette fois en rendant l'image elle-même cliquable. Dans cette version, on affiche l'image suivante en cliquant sur l'image elle-même. Remarquez que dans cette version on ne peut affichée que l'image suivante. L'affichage est toujours circulaire : quand on a affiché la dernière image et qu'on demande à afficher la suivante, on affiche la première image.

Fichier(s)

exo2.html , exo2.js

Le mot-clef this

Le mot-clef this n'est pas du tout spécifique aux images, mais ce chapitre est propice à sa présentation. Lors d'un évènement produit sur un élément, il est très fréquent que l'action JavaScript associée s'effectue sur ou implique ce même élément. Dans ce cas, il faut un moyen pour accéder. Reprenons par exemple l'exemple précédent :

<p>
  <p>
    Cliquez sur l'image d'un pays pour voir une vue de sa capitale
  </p>
  <div>
    <img class="miniature" src="afds.jpg" onclick="voir('pretoria.jpg');" />
    <img class="miniature" src="usa.jpg" onclick="voir('washington.jpg');" />
    <img class="miniature" src="vietnam.jpg" onclick="voir('hanoi.jpg');" />
    <img class="miniature" src="allemagne.jpg" onclick="voir('berlin.jpg');" />
    <img class="miniature" src="australie.jpg" onclick="voir('canberra.jpg');" />
  </div>
  <img id="capitale" src="pretoria.jpg" />
</p>	

Ici, on passe en paramètre de la fonction voir le nom du fichier source correspondant à l'image à afficher dans l'élément d'identifiant capitale. Une bien meilleure solution consisterait à ajouter le nom de ce fichier source comme attribut de chaque image, comme par exemple :

<img class="miniature" src="afds.jpg" data-file="pretoria.jpg" />

Dans ce cas, au lieu du nom du fichier, on voudrait passer en paramètre à la fonction voir l'élément IMG lui-même puisqu'il contient maintenant le nom du fichier comme valeur de l'attribut data-file. On peut utiliser le mot-clef this :

<p>
  <p>
    Cliquez sur l'image d'un pays pour voir une vue de sa capitale
  </p>
  <div>
    <img class="miniature" src="afds.jpg" data-file="pretoria.jpg" onclick="voir(this);" />
    <img class="miniature" src="usa.jpg" data-file="washington.jpg" onclick="voir(this);" />
    <img class="miniature" src="vietnam.jpg" data-file="hanoi.jpg" onclick="voir(this);" />
    <img class="miniature" src="allemagne.jpg" data-file="berlin.jpg" onclick="voir(this);" />
    <img class="miniature" src="australie.jpg" data-file="canberra.jpg" onclick="voir(this);" />
  </div>
  <img id="capitale" src="pretoria.jpg" />
</p>  

La fonction voir prend maintenant en paramètre l'élément HTML IMG sur lequel on a cliqué :

function voir( elt ) {
	document.querySelector( "#capitale" ).src = elt.getAttribute( "data-file" );
}

L'exemple précédent est disponible dans les fichiers exemple-2.html et exemple-2.js

Exercice 3

Complétez les fichiers exo3.html et exo3.js de façon que la page HTML correspondante affiche une gallerie d'images de taille réduite, et permette, lors du survol de l'une de ces images avec la souris, d'afficher l'image en taille normale ainsi que sa légende, respectivement dans l'élément IMG et dans l'élément P prévus à cet effet. La légende est la valeur de l'attribut title des images de taille réduite.

Fichier(s)

exo3.html , exo3.js

Retour sur les fonctions querySelector*

Nous avons déjà étudié les fonctions querySelector et querySelectorAll. Ces deux fonctions sont contextuelles : elles retournent respectivement la première occurence ou bien tous les éléments d'un type donné contenus dans la page HTML si on les applique à l'objet document. Cependant, on peut ne pas les appliquer à l'objet document mais à un élément particulier et dans ce cas on obtient le ou les éléments contenus dans cet élément particulier. Par exemple, le code suivant :

var imagesDocument = document.querySelectorAll( "img" );
var container = document.querySelector( "#container" );
var imagesContainer = container.querySelectorAll( "img" );

permet de récupérer

Exercice 4

Pour cet exercice, vous devez travailler dans le serveur web (et non pas en mode file). Le but de l'exercice est de réaliser un jeu de puzzle. Une grande partie de l'exercice est fournie et vous n'avez qu'à compléter le JavaScript. Vous devez télécharger l'archive exo4.zip qui contient tous les éléments nécessaires à la réalisation de l'exercice. Pour vous expliquer le fonctionnement du jeu, une démonstration sera faite durant le cours. Suivez attentivement cette démonstration et analysez le code HTML avec soin avant de vous lancer dans l'écriture du JavaScript.

Fichier(s)

exo4.zip

Solution(s)

exo4.js

Exercice 5

Pour cet exercice, vous devez travailler dans le serveur web (et non pas en mode file). Le but de l'exercice est de réaliser un jeu de morpion. Une grande partie de l'exercice est fournie et vous n'avez qu'à compléter le JavaScript. Vous devez télécharger l'archive exo5.zip qui contient tous les éléments nécessaires à la réalisation de l'exercice. Pour vous expliquer le fonctionnement du jeu, une démonstration sera faite durant le cours. Suivez attentivement cette démonstration et analysez le code HTML avec soin avant de vous lancer dans l'écriture du JavaScript. Le fichier exo5.js contient des squelettes de fonctions, des variables globales, ainsi que des fonctions déjà écrites. Essayez de comprendre l'architecture proposée et complétez le fichier JavaScript en conséquence.

Fichier(s)

exo5.zip

Solution(s)

exo5.js

La fonction setInterval

La fonction setInterval est une des deux fonction de délai en JavaScript. La fonction setInterval permet de répéter l'exécution d'un code JavaScript (contenu dans une fonction) à intervalle régulier. Par exemple, le code HTML suivant :

<body onload="demarrer()">
  <header>
    <h1>Exemple 5</h1>
  </header>
  <p>
    Compteur : <span id="compteur">0</span>
  </p>
</body>
associé au code JavaScript suivant :
function compter() {
	var compteurElt = document.querySelector( "#compteur" );
	compteurElt.innerHTML = Number( compteurElt.innerHTML ) + 1;
}

function demarrer() {
	setInterval( compter, 1000 );
}	
permet de réaliser un compteur simple. Au chargement de la page HTML, la fonction demarrer est appelée via l'évènement onload sur l'élément BODY. Cette fonction lance un setInterval : à partir de l'exécution de la fonction setInterval et toutes les 1000 millisecondes, la fonction compter est appelée. Cette fonction mets simplement à jour le contenu de l'élément d'identifiant compteur en ajoutant 1 à son contenu, et ce, toutes les secondes.

L'exemple précédent est disponible dans les fichiers exemple-3.html et exemple-3.js

Exercice 6

Reprenez l'exercice 2, mais dans cette nouvelle version, le diaporama est automatique : dès le chargement de la page, le diaporama se lance automatiquement et les images défilent à intervalle régulier. Comme dans l'exercice 2, les images défilent de façon circulaire.

Fichier(s)

exo6.html , exo6.js

La fonction clearInterval

la fonction clearInterval permet d'annuler un setInterval. Par exemple, on peut modifier le code HTML précédent afin de pouvoir alternativement stopper et redémarrer le compteur à l'aide d'un bouton :

<body onload="demarrer()">
  <header>
    <h1>Exemple 6</h1>
  </header>
  <p>
    Compteur : <span id="compteur">0</span> 
    <button id="bouton" onclick="stopStart()">STOP</button>
  </p>
</body>
Voilà le code JavaScript associé à ce code HTML :
var handler = null;

function compter() {
	var compteurElt = document.querySelector( "#compteur" );
	compteurElt.innerHTML = Number( compteurElt.innerHTML ) + 1;
}

function demarrer() {
	handler = setInterval( compter, 1000 );
}

function stopStart() {
	var boutonElt = document.querySelector( "#bouton" );
	if ( handler == null ) {
		handler = setInterval( compter, 1000 );
		boutonElt.innerHTML = "STOP";
	}
	else {
		clearInterval( handler );
		handler = null;
		boutonElt.innerHTML = "START";
	}
}
Lorsqu'on l'appelle, la fonction setInterval retourne une valeur qu'on appelle un handler : cette valeur permet d'annuler l'effet du setInterval via la fonction clearInterval. La fonction clearInterval prend en paramètre le handler retourné par la fonction setInterval. Dans l'exemple précédent, remarquez l'intérêt de remettre la variable handler à null : la fonction stopStart détermine l'action en effectuer (redémarrer le compteur ou bien l'arrêter) en fonction de la valeur de cette variable.

L'exemple précédent est disponible dans les fichiers exemple-4.html et exemple-4.js

Exercice 7

Reprenez l'exercice précédent, mais dans cette nouvelle version, le diaporama peut être stoppé et redémarré simplement en cliquant sur l'image elle-même !

Fichier(s)

exo7.html , exo7.js

Exercice 8

Complétez le fichier exo8.js de façon que le code HTML du fichier exo8.html affiche une horloge digitale. Cette horloge est affichée à l'aide de six images, deux images (pour les unités et les dizaines) pour les heures, deux images (pour les unités et les dizaines) pour les minutes et deux images (pour les unités et les dizaines) pour les secondes. Chaque seconde, l'horloge est mis à jour avec les nouvelles valeurs pour le nombre de secondes, de minutes et d'heures. Pour obtenir ces valeurs, il suffit de calculer la date courante et de les en extraire via les fonctions getHours, getMinutes et getSeconds.

Fichier(s)

exo8.html , exo8.js , exo8.zip

La fonction setTimeout

La fonction setTimeout est une des deux fonction de délai en JavaScript. Cette fonction permet d'exécuter du code JavaScript (contenu dans une fonction) après qu'un certain temps se soit écoulé. Par exemple, le code HTML suivant :

<body onload="demarrer()">
  <header>
    <h1>Exemple 3</h1>
  </header>
  <p>
    Vous cherchez un bon cours sur JavaScript ?
    Vous avez être redirigé vers une nouvelle page...
  </p>      
</body>
associé au code JavaScript suivant :
function rediriger() {
	window.location.href = "http://users.polytech.unice.fr/~gaetano/imapp/";
}

function demarrer() {
	setTimeout( rediriger, 5000 );
}	
permet de charger automatiquement une nouvelle page au bout de 5 secondes. Au chargement de la page HTML, la fonction demarrer est appelée via l'évènement onload sur l'élément BODY. Cette fonction lance un timeout : à partir de l'exécution de la fonction setTimeout et après 5000 millisecondes, la fonction rediriger est appelée, et charge une nouvelle page.

L'exemple précédent est disponible dans les fichiers exemple-5.html et exemple-5.js

La fonction clearTimeout

A la manière de clearInterval, la fonction clearTimeout permet d'annuler un setTimeout. Lorsqu'on l'appelle, la fonction setTimeout retourne une valeur qu'on appelle un handler : cette valeur permet d'annuler l'effet du setTimeout via la fonction clearTimeout. Reprénons l'exemple précedent, mais cette fois avec la possibilité d'annuler la redirection en cliquant sur un bouton :

<body onload="demarrer()">
  <header>
    <h1>Exemple 4</h1>
  </header>
  <p>
    Vous cherchez un bon cours sur JavaScript ?
    Vous avez être redirigé vers une nouvelle page...
  </p>
  <p>
    Si vous ne voulez pas être redirigé, cliquez <button onclick="annuler()">ici</button>
  </p>
  <p id="message">
    Ok, vous restez sur cette page !
  </p>
</body>	
Il est maintenant possible d'annuler le setTimeout et donc, la redirection, en cliquant sur le bouton, c'est à dire en exécutant la fonction annuler :
var handler = null;

function rediriger() {
	window.location.href = "http://users.polytech.unice.fr/~gaetano/imapp/";
}

function demarrer() {
	handler = setTimeout( rediriger, 5000 );
}

function annuler() {
	clearTimeout( handler );
	document.querySelector( "#message" ).style.visibility = "visible";
}	
A la manière de la fonction clearTimeout, la fonction setTimeout retourne une valeur qu'on stocke dans la variable globale handler. Pour annuler le setTimeout, il suffit alors d'appeler la fonction clearTimeout avec la valeur de handler en paramètre.

L'exemple précédent est disponible dans les fichiers exemple-6.html et exemple-6.js

Exercice 9

Complétez le fichier exo9.js de façon que le code HTML du fichier exo9.html affiche une question type QCM à temps limité : après le chargement de la page, l'utilisateur dispose d'un temps limité pour cocher la bonne réponse. S'il coche une mauvaise réponse avant la limite, le message adéquat est affiché et il peut faire une nouvelle tentative. S'il coche la bonne réponse avant la limite, le message adéquat est affiché. S'il n'arrive pas à cocher la bonne réponse avant la limite, le message adéquat s'affiche. Enfin, s'il coche une réponse après la limite, un message s'affiche lui signalant qu'il a soit déjà bien répondu, soit déjà mal répondu.

Fichier(s)

exo9.html , exo9.js

Fonctions set* et paramètres

Dans certain cas, il est nécessaire de passer des paramètres aux fonctions activées par un setTimeout ou un setInterval. Ce passage de paramètres est un peu particulier puisqu'on va préciser ces paramètres avant que la fonction soit appelée. On le réalise en ajoutant simplement les paramètres en question à la suite du paramètre de temps. Voici la syntaxe d'un setInterval activant la fonction f avec les paramètres parametre1 et parametre2 :

setInterval( fonction, temps, parametre1, parametre2 )
Vous expérimenterez vous-même cette construction dans l'exercice suivant.

Exercice 10

Pour cet exercice, vous devez travailler dans le serveur web (et non pas en mode file). Le but de l'exercice est de réaliser un jeu de type memory. Une grande partie de l'exercice est fournie et vous n'avez qu'à compléter le JavaScript. Vous devez télécharger l'archive exo10.zip qui contient tous les éléments nécessaires à la réalisation de l'exercice. Pour vous expliquer le fonctionnement du jeu, une démonstration sera faite durant le cours. Suivez attentivement cette démonstration et analysez le code HTML avec soin avant de vous lancer dans l'écriture du JavaScript. Le fichier exo10.js contient des squelettes de fonctions et des variables globales. Essayez de comprendre l'architecture proposée et complétez le fichier JavaScript en conséquence.

Fichier(s)

exo10.zip