jQuery: slideshow di immagini object-oriented

jQuery: slideshow di immagini object-oriented

Realizzare uno slideshow di immagini con jQuery è una tappa ineludibile per ogni sviluppatore web. La realizzazione può presentare delle difficoltà la prima volta che la si affronta, soprattutto se non si conosce il segreto di ogni slideshow: gli indici degli array. Proprio così: sia che si selezionino le immagini o che si faccia scorrere il loro contenitore, tutto dipende dall'incrementare e decrementare l'indice di un array che può essere sia costituito dalle immagini stesse (intese come elementi DOM) sia dagli offset di tali immagini. In questo articolo vi mostrerò come realizzare uno slideshow di immagini che oltre ai due soliti controlli per muoversi tra le immagini mostrerà anche il numero dell'immagine corrente.

Partiamo dalla marcatura. Oltre ai due soliti contenitori per lo slideshow abbiamo bisogno anche di un contenitore per i nostri controlli:


<div id="slideshow">

	<div id="slideshow-wrapper">
	
		<img src="1.jpg" alt="" />
		<img src="2.jpg" alt="" />
		<img src="3.jpg" alt="" />
		<img src="4.jpg" alt="" />
		<img src="5.jpg" alt="" />
		<img src="6.jpg" alt="" />
	
	</div>

</div>

<div id="slideshow-actions">
	<ul>
		<li><a href="#" id="prev">Precedente</a></li>
		<li><a href="#" id="next">Successiva</a></li>
		<li id="slideno"></li>
	</ul>
</div>

Da un punto di vista semantico l'uso di un elemento vuoto come la voce di lista con ID slideno (che conterrà il numero dell'immagine corrente) non è perfettamente consigliabile. Se per voi è importante questo aspetto, potete aggiungere tale elemento con jQuery.

Il nostro CSS sarà invece il seguente:


#slideshow {
	width: 600px;
	height: 400px;
	margin: 0 auto;
	position: relative;
	overflow: hidden;
}

#slideshow-wrapper {
	width: 3600px;
	height: 400px;
	position: relative;
}

#slideshow-wrapper img {
	float: left;
	width: 600px;
	height: 400px;
}

#slideshow-actions {
	width: 600px;
	margin: 0.5em auto;
	padding: 0.5em;
	background: #333;
	border-radius: 6px;
}

#slideshow-actions ul {
	margin: 0;
	padding: 0;
	list-style: none;
	height: 100%;
	text-align: center;
}

#slideshow-actions li {
	display: inline;
	margin-right: 0.5em;
	font-size: 90%;
	font-weight: bold;
	color: #fff;
}

#slideshow-actions a {
	color: #fff;
	text-decoration: none;
}

Sicuramente definire in anticipo la larghezza massima del contenitore più interno (3600 pixel, poichè ciascuna delle sei immagini è larga 600 pixel e alta 400 pixel) rende più veloce il rendering del nostro layout ma non è consigliabile quando non conosciamo in anticipo il numero di immagini che saranno presenti. Per questo motivo si può utilizzare jQuery per questo scopo:


$('#slideshow-wrapper', '#slideshow').
css('width', 600 * $('img', '#slideshow-wrapper').length);

Questa tecnica dinamica viene anche usata spesso da molti plugin per jQuery.

A questo punto dobbiamo implementare due cose:

  1. l'effetto di scorrimento
  2. la visualizzazione del numero dell'immagine corrente

Per rendere più flessibile e riusabile il nostro codice creiamo un oggetto Slideshow che avrà un solo metodo pubblico (slide()) per gestire la nostra implementazione, un metodo privato (getSlidePositions()) che restituirà un array con gli offset delle immagini e diverse proprietà private che ci serviranno per selezionare gli elementi necessari.

Cominciamo con i membri privati del nostro oggetto:


var Slideshow = new function() {

  var index = 0;
  var prev = $('#prev', '#slideshow-actions');
  var next = $('#next', '#slideshow-actions');
  var slides = $('img', '#slideshow-wrapper');
  var wrapper = $('#slideshow-wrapper');
  var slideNo = $('#slideno', '#slideshow-actions');
  
  var getSlidePositions = function() {
  
    var positions = [];
    
    slides.each(function(i) {
    
      var left = $(this).position().left;
      positions[i] = left;
    
    
    });
  
    return positions;
  };
  
  
  // continua
}();

Abbiamo quindi:

  • index: impostato inizialmente a zero, sarà incrementato e decrementato per muoverci nell'array di offset restituito da getSlidePositions()
  • prev, next: riferimenti ai due link che fungono da controlli
  • slides: riferimento all'intero set di immagini dello slideshow
  • wrapper: riferimento al contenitore interno dello slideshow, che dovrà scorrere
  • slideNo: l'elemento vuoto che andrà a contenere il numero dell'immagine corrente
  • getSlidePositions(): restituisce un array di offset delle immagini ottenuto tramite l'oggetto position() e la sua proprietà left

Ora dobbiamo implementare il metodo pubblico. In pratica dobbiamo:

  1. incrementare l'indice sul controllo 'Successiva' e
    1. verificare che l'indice non abbia raggiunto il limite costituito dal numero massimo di immagini (in tal caso reimpostarlo a 0)
    2. usare animate() facendo scorrere il contenitore interno con un valore negativo preso dall'array di offset
    3. mostrare il numero dell'immagine corrente sommando all'indice il valore 1
  2. decrementare l'indice sul controllo 'Precedente' e
    1. verificare che l'indice non sia uguale a -1 (in tal caso reimpostarlo sul numero di immagini massimo meno 1)
    2. usare animate() facendo scorrere il contenitore interno con un valore negativo preso dall'array di offset
    3. mostrare il numero dell'immagine corrente sommando all'indice il valore 1

Il codice sarà:


// continua
this.slide = function() {
  
    var offsets = getSlidePositions();
    var len = offsets.length;
    
    
    
    prev.click(function(event) {
    
      index--;
      
      if(index == -1) {
      
        index = 5;
      
      }
      
      
      wrapper.animate({
        left: - offsets[index]
      }, 'slow', function() {
      
        slideNo.text(index+1);
      
      
      });
      
      event.preventDefault();
    
    
    });
    
    next.click(function(event) {
    
      index++;
      
      if(index == len) {
      
        index = 0;      
      
      
      }
      
      wrapper.animate({
        left: - offsets[index]
      }, 'slow', function() {
      
        slideNo.text(index+1);
      
      
      });
      
      event.preventDefault();
    
    
    
    });
  
  
};

A questo punto per creare lo slideshow non dobbiamo fare altro che usare il seguente codice:


$(function() {

  Slideshow.slide();

});

Il codice è assolutamente perfettibile, ma quello che mi preme sottolineare è che con questo approccio orientato agli oggetti possiamo di fatto riusare questo slideshow in molti altri contesti. Alla fine avremo una sola riga di codice per richiamare lo slideshow nella nostra pagina quando il DOM ha completato il suo caricamento.

Potete visionare l'esempio finale in questa pagina.

Torna su