Owl Carousel - Scrollbarpar McTaylis

Dans le cadre d'un projet de refonte complète du site d'une école d'ingénieurs, j'ai été amené à mettre en place un système d'affichage de flux de données en carrousels, à l'aide du plugin jQuery : Owl Carousel.

Cependant, lorsque l'on m'a demandé d'y ajouter une scrollbar horizontale pour faciliter la navigation, un problème s'est vite posé : aucune option ni aucun plugin ne permet d'ajouter cette fonctionnalité (du moins, par encore). Je me suis donc attelé à sa réalisation, que j'ai décidé de partager avec vous, qui est loin d'être parfaite mais reste tout de même fonctionnelle.

Code

La structure HTML

<section id="carousel">
			<nav>
			<div class="prev">Precedent</div>
			<div class="next">Suivant</div>
			</nav>
			<div id="list" class="owl-carousel owl-theme">
			<div class="item"><h1>1</h1></div>
			<div class="item"><h1>2</h1></div>
			<div class="item"><h1>3</h1></div>
			<div class="item"><h1>4</h1></div>
			<div class="item"><h1>5</h1></div>
			<div class="item"><h1>6</h1></div>
			<div class="item"><h1>7</h1></div>
			<div class="item"><h1>8</h1></div>
			<div class="item"><h1>9</h1></div>
			</div>
			<div class="scrollbar">
			<div class="bar-container">
			<div class="bar"></div>
			</div>
			</div>
		</section>

Quelques règles CSS pour styliser la scrollbar et le carrousel

#carousel { width: 1200px; position: relative; margin: 0 auto; }
			.owl-item { background-color: #e1e1e1; text-align: center; padding: 42px 0; }

			.scrollbar { width: 100%; height: 1px; position: relative; }
			.scrollbar .bar-container { position: absolute; left: 0; top: -2px; padding: 12px 0; }
			.scrollbar .bar-container:hover .bar, .scrollbar .bar-container:active .bar { background-color: #00aef0; }
			.scrollbar .bar-container .bar { height: 4px; background: #bbb; width: 100%; }

			nav div { display: inline-block; padding: 12px; cursor: pointer; font-family: Arial, sans-serif; font-size: 14px; margin-bottom: 12px; background-color: #00aef0; color: #fff; }
		nav div.disabled { background-color: #e1e1e1; color: #fff; }

Et toute la gestion de l'animation en jQuery

$(document).ready(function() {
			var owl = $('#list');

			// Initialise la taille de la barre en fonction du nombre d’éléments dans le carrousel
			owl.on('initialized.owl.carousel', function(e)
			{
				var perPage = e.page.size;
				var itemCount = $('#carousel .item').length - (perPage - 1);
				var barWidth = 100 / itemCount;
				$('.scrollbar .bar-container').css('width', barWidth+'%');
			});

			owl.owlCarousel({
				loop: false,
				margin: 24,
				dots: false,
				nav: false,
				items: 3,
				center: false,
			});

			// Mouvement de la scrollbar au clic sur une navigation personnalisée
			$('nav .prev').on('click', function(){
				owl.trigger('prev.owl.carousel');
				var currentIndex = $('.owl-item.active').index();
				var barPosition = $('.scrollbar .bar-container').width() * currentIndex;
				$('.scrollbar .bar-container').animate({left: barPosition},200);
			});

			$('nav .next').on('click', function(){
				owl.trigger('next.owl.carousel');
				var currentIndex = $('.owl-item.active').index();
				var barPosition = $('.scrollbar .bar-container').width() * currentIndex;
				$('.scrollbar .bar-container').animate({left: barPosition},200);
			});

			// Détection des premiers et derniers éléments du carrousel
			owl.on('changed.owl.carousel', function(e)
			{
				if(e.item.index == 0)
				{
					$('nav .prev').addClass('disabled');
				}
				else if(e.item.index == e.item.count - e.page.size)
				{
					$('nav .next').addClass('disabled');
				}
				else
				{
					$('nav .prev, nav .next').removeClass('disabled');
				}
			});

			// Déplacement de la scrollbar si le carrousel est déplacé en mode "drag"
			owl.on('dragged.owl.carousel', function(e)
			{
				var barPosition = $('.scrollbar .bar-container').width() * e.item.index;
				$('.scrollbar .bar-container').animate({left: barPosition},200);
			});

			// Configuration du comportement de la scrollbar
			$('.scrollbar .bar-container').draggable({
				axis: 'x',
				containment: 'parent',
				drag: function(e, ui) 
				{
					// Calcul de l'index de l'élément à afficher, en fonction de la position de la barre
					var scrollPos = Math.round(ui.position.left / $('.scrollbar .bar-container').width());
					owl.trigger('to.owl.carousel', scrollPos);
				}
			});
		});

La partie jQuery est bien entendue perfectible : une amélioration du code permettrait d'utiliser la scrollbar avec les boutons de navigation du plugin, ou encore déplacer automatiquement la barre aux limites quand le premier ou dernier élément du carrousel est atteint.