Image de l'article Un carrousel d'image centré avec jQuery

Un carrousel d'image centré avec jQuery

Pour les besoins d'un client je devais créer un défilement d'image infini... avec l'image principale centrée.
Le but est donc d'avoir une image centrée et d'afficher une partie de l'image précédente et une partie de l'image suivante. Le défilement des images est infini.

Démo

Le code HTML


<div id="photoSlideWrap">
	<div id="photoSlide">
		<div id="photo1"> </div>
		<div id="photo2"> </div>
		<div id="photo3"> </div>
		<div id="photo4"> </div>
	</div><!--photoSlide-->
</div><!--photoSlideWrap-->

Le bloc #photoSlideWrap défini la zone de visibilité de nos images, #photoSlide contient toutes les images affichées les unes derrière les autres. C'est ce bloc qui sera animé en jQuery.

Principe de fonctionnement de cSlideShow

Les images sont placées dans des blocs < div >, mais elles pourraient être affichés directement ou placé dans une liste < ul >. Adoptez le type d'élément qui vous convient.
Les images sont placées dans l'ordre d'affichage, c'est le code Javascript qui modifie l'ordre des images, pas nous. Il faut au minimum 4 images sinon l'effet ne fonctionne pas.

Les styles


#photoSlideWrap{
	margin: auto;
	width: 100%;
	overflow: hidden;
}
#photoSlide > div{
	float: left;
	width: 950px;
	height: 100px;
}
#photo1{
	background-color: #ff33bb;
}
#photo2{
	background-color: #37c448;
}
#photo3{
	background-color: #0047d9;
}
#photo4{
	background-color: #4d81d3;
}

Ici rien de sorcier, on affiche #photoSlideWrap sur toute la largeur de la page (width: 100%;), on masque les éventuels ascenseurs (overflow: hidden;) et on centre le bloc (margin: auto;).

On définit la dimension des enfants de #photoSlide (#photoSlide > div) et, pour l'exemple, on applique une couleur de fond à chaque bloc.

Vous remarquerez qu'on ne définit pas la largeur de #photoSlide, c'est jQuery qui va la calculer pour nous.

Le code Javascript

Passons au plus intéressant! Nous allons utiliser jQuery pour l'animation et le déplacement des éléments DOM, bien qu'on pourrait s'en passer il apporte un certain confort dans la conception.


function cSlideShow(id, autoStart){

Début de déclaration de l'objet. Deux paramètres sont attendus, en premier l'identifiant de l'élément à animer, en second un boolean facultatif pour préciser si l'animation doit démarrer immédiatement ou pas.


var me = this; // on enregistre l'objet dans une variable pour y avoir accès dans les fonctions
me.id = id; // identifiant de l'élément à animer
me.slideWidth = $("#"+me.id+" > div:first").width(); // largeur d'un enfant de #id. on enregistre la largeur du premier div, on part du principe qu'ils ont tous la même largeur.
me.posXMin = 0; // position X minimale de #id (calculé dans la fonction init)
me.posXMax = 0; // position X maximale de #id (calculé dans la fonction init)
me.scrollSpeed = 1000; // vitesse de défilement (en milliseconde)
me.scrollInterval = 5000; // intervale entre deux animation (en milliseconde)
me.scrollLeft = 1; // défilement vers la gauche
me.scroll = 0; // défilement en cours
me.intervalObj = ''; // objet crée par setInterval
me.functionAfter = ''; // fonction facultative appelé avant l'animation
me.functionBefore = ''; // fonction facultative appelé après l'animation

Initialisation des variables de l'objet.


me.init = function(){
	var p = $("#"+me.id).parent().width();
	var d = $("#"+me.id).children().size()*me.slideWidth
	if(p<d) me.posX = Math.abs(me.slideWidth-(p-me.slideWidth)/2);
	else me.posX = 0;
	me.posMaxX = me.posX+me.slideWidth;
	$("#"+me.id).css({marginLeft:-me.posX, width: d});
}

init() est appelé à la création de l'objet et lors d'un redimensionnement. On calcule les positions minimale et maximale, ainsi que la largeur de #id. On part du principe que les images ont toutes la même largeur.
L'intérêt de laisser jQuery définir la largeur de #id est qu'on n'aura pas besoin de s'en occuper quand on voudra ajouter ou supprimer des images.


me.animStart = function(play){
	me.animStop();
	me.intervalObj = setInterval(me.animPrepare, me.scrollInterval);
	if(play) me.anim();
}

animStart() efface et créer un nouvel objet d'intervalle. Si play=1, on lance immédiatement l'animation.


me.animStop = function(){
	clearInterval(me.intervalObj);
}

animStop() efface l'objet d'intervalle.


me.animToLeft = function(){
	if(me.scrollLeft==0) $("#"+me.id).css({marginLeft:-me.posXMin}).append($("#"+me.id+" > div:first"));
	me.scrollLeft = 1;
	me.animPrepare();
}

animToLeft() déplace les images vers la gauche. Si le défilement était précédemment vers la droite, il faut déplacer la première image en dernière position.


me.animToRight = function(){
	if(me.scrollLeft==1) $("#"+me.id).css({marginLeft:-me.posXMax}).prepend($("#"+me.id+" > div:last"));
	me.scrollLeft = 0;
	me.animPrepare();
}

animToRight() déplace les images vers la droite. Comme pour la fonction animToLeft si le défilement était vers la gauche, il faut déplacer la dernière image en première position.


me.animPrepare = function(){
	if(me.functionBefore) me.functionBefore();
	else me.animStart(1);
}

La fonction animPrepare() permet d'appeler une fonction avant le défilement des images. Par exemple pour faire un fondu par exemple.
Si vous avec défini une fonction elle devra appeler animStart(1) pour lancer l'animation une fois terminée.


me.anim = function(){
	if(me.scroll) return 0;
	me.scroll = 1;
	if(me.scrollLeft){
		$("#"+me.id).animate({marginLeft:-me.posXMax},me.scrollSpeed,function(){
			$(this).css({marginLeft:-me.posXMin}).append($("#"+me.id+" > div:first"));
			if(me.functionAfter) me.functionAfter();
			me.scroll = 0;
		})
	}else{
		$("#"+me.id).animate({marginLeft:-me.posXMin},me.scrollSpeed,function(){
			$(this).css({marginLeft:-me.posXMax}).prepend($("#"+me.id+" > div:last"));
			if(me.functionAfter) me.functionAfter();
			me.scroll = 0;
		})
	}
}

anim() est fonction principale qui gère l'animation du bloc div. On vérifie si la variable scroll=0. Si oui on continue sinon on retourne 0.
Cela évite de redemander une nouvelle animation à jQuery avant que l'animation en cours ne soit terminé. On définit scroll = 1;

Pour le défilement à droite ou à gauche le principe est le même. On gère le défilement en animant la marge gauche du conteneur #id. Une fois le défilement terminé, on réinitialise la marge du conteneur et on déplace un de ses blocs enfant :
- Le premier en dernière position dans le cas d'un défilement à gauche
- Le dernier en première position dans le cas d'un défilement à droite

On appelle ensuite la fonction de callback si elle est définie.

Enfin on définit la variable scroll à 0.


me.getCurrentSlideId = function(){
	return $("#"+me.id+" > div:nth-child("+(me.scrollLeft ? 2:3)+")").attr('id');
}

getCurrentSlideId() renvoi l'identifiant du bloc div qui est affiché au centre. Si la défilement est vers la gauche il s'agit du deuxième enfant de #id, si le défilement est vers la droite, c'est le troisième. jQuery est très utile dans ces situations où tous peut se faire en une ligne.


$(window).resize(function(){
	me.init();
});
me.init();
// place le dernier élément au début
$("#"+me.id).prepend($("#"+me.id+" > div:last"));
// démarre l'animation si autoStart!=0
if(autoStart!=0) me.animStart();

Fin de déclaration de l'objet.
1- Attache la fonction init() au redimensionnement de fenêtre. Nécessaire si la zone de visilité de nos images (#photoSlideWrap dans mon exemple) est de 100%
2- Appelle la fonction init() pour définir les variables posXMin et posXMax.
3- Déplace le dernier enfant de $("#"+me.id) en première position avec la fonction jQuery prepend().
4- Enfin si autoStart est égal à 1; on lance immédiatement l'animation.

Utilisation


var s = new cSlideShow('photoEntete');

L'utilisation la plus simple est de créer l'objet cSlideShow avec l'identifiant du bloc qui contient les images en paramètres. Tout simplement !


var s = new cSlideShow('photoEntete', 0);
s.scrollSpeed = 1000;
s.scrollInterval = 9000;
s.functionBefore = maFonction1;
s.functionAfter = maFonction2;
s.animStart();

Vous pouvez également créer l'objet cSlideShow sans lancer l'animation (autoStart=0). Il est alors possible de redéfinir les variables de l'objet, comme la vitesse de défilement (scrollSpeed), le temps de pause (scrollInterval) et les fonctions qui seront appelées avant et après le défilement (functionBefore et functionAfter).

On termine en lançant l'animation avec animStart().


$("#btLeft").click(function(){
	s.animToLeft();
});
$("#btRight").click(function(){
	s.animToRight();
});

Il est également possible d'attribuer à des boutons les fonctions de défilement de l'objet cSlideShow grâce à jQuery...


$("#btStop").click(function(){
	if($(this).prop('value')=='Start'){
		s.animStart();
		$(this).prop('value', 'Stop');
	}else{
		s.animStop();
		$(this).prop('value', 'Start');
	}
});

… ou encore une fonction lecture / pause en appelant les fonctions animStart animStop.

Téléchargement

Afficher un exemple concret de l'objet cSlideShow

Cet exemple de fonctionnement contient tout le code javascript décrit dans cette page. L'objet ne demande qu'à être améliorer.

Amusez-vous bien !

Article précédent : Gabarit Photoshop pour les chaînes Youtube 2013

Article suivant : Perte des bases clients chez Adobe un petit rappel

 

Image Viewer