jQuery: gestire i timer e la coda di animazioni negli slideshow

jQuery: gestire i timer e la coda di animazioni negli slideshow

Giorni fa un mio lettore mi ha segnalato un problema su uno slideshow che avevo creato tempo fa. In pratica lo scorrimento "impazziva" quando si cliccava due volte consecutivamente su un bottone di navigazione. Lo slideshow usava un timer ciclico che veniva messo in pausa quando si usavano i bottoni di navigazione. Come giustamente segnalato dal lettore, il problema stava nella coda di animazioni creata da jQuery. Fortunatamente esiste una soluzione.

Occorre capire che animazioni e timer dovrebbero avere sempre la stessa durata. Se avete due animazioni per slide della durata complessiva di 2000 millisecondi, l'intervallo del timer dovrebbe essere di 2000 millisecondi.

Questo perchè bisogna dare il tempo alle animazioni di completare il loro ciclo. Tuttavia, se si lanciano due timer consecutivamente attraverso due clic su un bottone di navigazione, l'effetto è imprevedibile.

La soluzione sta nel resettare la coda di animazioni su ciascuna slide quando queste sono complete:


function animateSlide(slide) {

	$('div.a', slide).fadeIn(1000, function() {
	
		$('div.b', slide).animate({
			left: 100
		}, 1000);
	
	});

}

In questo caso la sequenza è:

  1. assolvenza (1 secondo)
  2. spostamento (1 secondo)

Ma cosa succede quando questa funzione è all'interno di un timer?


var timer = setInterval(function() {

	index++;
	
	if(index == slides.length) {
	
		index = 0;
	
	}
	
	var slide = slides.eq(index);
	
	wrapper.animate({
		left: - slide.position().left
	}, 1000, function() {
	
		animateSlide(slide);
	
	});

}, 3000);

In questo caso ai 2 secondi della prima sequenza si aggiunge un ulteriore secondo dello scorrimento dello slideshow. Nessun problema sin qui. Il problema è che se si lanciano contemporaneamente più timer la sequenza si moltiplica in modo abnorme e lo scorrimento "impazzisce" perchè il timer lavora più volte sullo stesso elemento simultaneamente.

La soluzione consiste nel resettare sia il timer che la coda di animazioni:


var reset = function() {

	clearInterval(timer);
	timer = null;
	$(':animated', '#slideshow').clearQueue();
	

};

Quindi possiamo risolvere il problema sui bottoni di navigazione. Per esempio:


$('#previous').click(function(event) {

	reset();
	
	// continua

	event.preventDefault();

});

In questo modo anche cliccando due volte non c'è più nessun timer nè animazione in esecuzione.

Torna su