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
-
à la ligne 1 : tous les éléments de type
IMG de la page HTML
-
à la ligne 2 : l'élément particulier d'identifiant
container
-
à la ligne 3 : tous les éléments de type
IMG contenus dans l'élément d'identifiant
container
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