jQuery : construire son propre diaporama infini
20 septembre 2009
Par Seb
Il existe de nombreuses librairies permettant de mettre en place un diaporama sur Internet, mais pour diverses raisons il est parfois nécessaire de mettre en place son propre système. Nous allons voir ici comment concevoir et mettre en place un diaporama à défilement infini.
Le but ici est de vous donner une base de départ qui pourra être étendue et adaptée à vos besoins.
Le principe
Le diaporama est composé de deux parties : le cadre fixe, souvent composé d’un DIV ou d’un UL, et les diapos à proprement parler, qui défilent dans le cadre :

Structure du diaporama
Tout ce qui dépasse du cadre est masqué, c’est ce qui donne cette illusion d’encadrement. Les éléments qui composent les diapos sont placés en position absolue, de façon à pouvoir être alignés horizontalement. Ensuite, le défilement se résume à déplacer les éléments à l’intérieur du cadre.
Ça semblait simple, jusque là
La difficulté dans la réalisation d’un diaporama infini tient au raccord entre la dernière diapo et la première : on ne souhaite pas voir le diaporama défiler à tout vitesse pour revenir au début, mais que la première diapo arrive naturellement à la suite de la dernière, sans rompre l’ordre de lecture, et que le défilement recommence à l’infini.
Pour cela, une petite astuce est nécessaire : lors de la mise en place du diaporama avec jQuery, nous allons copier la dernière diapo avant la première, et la première après la dernière :

Mise en place des éléments avec jQuery
De cette manière, lorsque notre diaporama arrivera à la fin et que nous cliquerons sur « suivant », il pourra encore défiler pour faire apparaître ce qui semble être la première diapo. Une fois le défilement terminé, l’ensemble se repositionnera sur la « vraie » première diapo, de façon totalement invisible pour l’utilisateur, et le défilement pourra continuer :

Cinématique du retour au début
Et dans l’autre sens, c’est exactement la même logique.
Résultat
Pour cet exemple, nous allons utiliser le marquage suivant :
<ul id="diaporama"> <li><a href="#" title="Titre du lien"><img src="images/img1.jpg" /></a></li> <li><a href="#" title="Titre du lien"><img src="images/img2.jpg" /></a></li> <li><a href="#" title="Titre du lien"><img src="images/img3.jpg" /></a></li> <li><a href="#" title="Titre du lien"><img src="images/img4.jpg" /></a></li> <li><a href="#" title="Titre du lien"><img src="images/img5.jpg" /></a></li> </ul>
Ce marquage présente l’avantage d’être simple à mettre en œuvre et compréhensible par les moteurs de recherche en même temps.
Le code jQuery est le suivant :
// Durée des diapos (en millisecondes)
var diapoDuration = 4000;
// Position actuelle du diaporama
var diapoPosition = 1;
// Identifiant d'intervale du diaporama
var diapoInterval;
// Mise en place au chargement
$(function() {
// On récupère le bloc principal
var blocDiapo = $('#diaporama');
// On duplique le premier et le dernier élément pour permettre la rotation infinie
var first = blocDiapo.children(':first');
var firstNode = first.get(0).nodeName;
var last = blocDiapo.children(':last');
var lastNode = first.get(0).nodeName;
blocDiapo.prepend('<'+lastNode+'>'+last.html()+'</'+lastNode+'>');
blocDiapo.append('<'+firstNode+'>'+first.html()+'</'+firstNode+'>');
// On positionne les diapos en ligne
var width = blocDiapo.innerWidth();
blocDiapo.children().each(function(i) {
$(this).css('left', (i*width)+'px');
});
// Mise en position sur la première diapo
blocDiapo.scrollLeft(width);
// Démarrage
diapoInterval = setTimeout('diaposScroll(1)', diapoDuration);
});
// Fonction de défilement du diaporama
function diaposScroll(value)
{
// On récupère le bloc principal
var blocDiapo = $('#diaporama');
// Arrêt des effets en cours
blocDiapo.stop(true,true);
// Si un timeout est en cours, on l'arrête
if (diapoInterval > 0)
{
clearTimeout(diapoInterval);
}
// Largeur du diaporama et nombre de diapos
var width = blocDiapo.innerWidth();
var nbChilds = blocDiapo.children().length-2;
// On met à jour la position
diapoPosition += value;
// Défilement suivant la valeur
if (diapoPosition < 1)
{
// Saut à la fin
diapoPosition += nbChilds;
blocDiapo.scrollLeft((diapoPosition+1)*width);
}
else if (diapoPosition > nbChilds)
{
// Retour au début
diapoPosition -= nbChilds;
blocDiapo.scrollLeft((diapoPosition-1)*width);
}
blocDiapo.animate({scrollLeft:(diapoPosition*width)}, 500);
// On lance le timeout suivant
diapoInterval = setTimeout('diaposScroll(1)', diapoDuration);
}
Et un petit peu de CSS pour pimenter le tout :
#diaporama {
overflow: hidden;
position: relative;
width: 400px;
height: 230px;
list-style-type: none;
padding: 0;
}
#diaporama li {
overflow: hidden;
position: absolute;
width: 400px;
height: 230px;
}
#diaporama li a {
display: block;
width: 400px;
height: 230px;
}
#diaporama li a img {
border: 0;
}
Et voilà, votre diaporama est prêt ! Vous pouvez voir l’exemple ici : http://www.display-inline.fr/demo/diaporama
Télécharger le code-source complet ainsi qu’un exemple fonctionnel :





[...] dans l’article. Par exemple, voici un lien vers la démonstration de l’article sur la création d’un diaporama infini [...]
Excellente démo ! merci.
Très bon article.
Petit problème remarqué lors de l’utilisation: parfois le diapo commence sur la dernière image (en fait sur celle, dupliquée, tout à gauche). Ceci arrive quand les images ne sont pas encore chargées et qu’à la ligne 30 (blocDiapo.scrollLeft(width);) le blocDiapo est encore ‘vide’.
Pour remédier à cela, j’ai utilisé (juste après cette ligne 30):
blocDiapo.find(« img »).eq(0).bind(« load »,function(){$(‘#diaporama’).scrollLeft(width)});
Comme ça le scroll se fait après que l’image soit chargée.
Merci pour l’astuce !