Costruire uno jQuery Image Scroller

In questo tutorial, costruiremo uno scroller di immagini, sfruttando le eccellenti funzionalità di animazione di jQuery e in generale divertendoci con il codice. Gli scrollers di immagini non sono certo nuovi; versioni di loro escono continuamente. Molti di essi tuttavia sono avviati dall'utente; il che significa che per cambiare il contenuto attualmente visualizzato, il visitatore deve fare clic su un pulsante o eseguire qualche altra azione. Questo scroller sarà diverso in quanto sarà completamente autonomo e inizierà lo scorrimento una volta caricata la pagina.


Il widget finito sarà completamente cross-browser e funzionerà come previsto nelle ultime versioni di tutti i browser più comuni. Creeremo anche in qualche interazione aggiungendo controlli che consentano al visitatore di cambiare la direzione dell'animazione. Lavoreremo solo con jQuery e un po 'di HTML e CSS in questo tutorial e dovremmo essere in grado di eseguire gli esempi senza una configurazione completa del server web.


Iniziare

Creiamo prima di tutto la pagina HTML sottostante; in una nuova pagina nel tuo editor di testo aggiungi il seguente codice:

      imageScroller Image Carousel   
Mela Firefox jQuery cinguettio Interfaccia utente di jQuery

Salva questo come imageScroller.html all'interno di una nuova cartella. Ci colleghiamo a un foglio di stile personalizzato nella parte superiore della pagina, che codificheremo tra poco, e includiamo un collegamento alla versione ospitata dell'ultima versione di jQuery nella parte inferiore della pagina. Caricamento di script alla fine del corpo è una tecnica riconosciuta per migliorare le prestazioni della tua pagina e dovrebbe quindi essere praticata ovunque possibile.

Il nostro widget consiste in una serie di contenitori nidificati e un mucchio di immagini racchiuse in collegamenti. Le immagini collocate all'interno dei contenitori sono codificate nella pagina per motivi di accessibilità. Non recupereremo le immagini dinamicamente; tutte le immagini inserite nel widget verranno automaticamente scrollate (a condizione che siano racchiuse in un collegamento con il nome della classe appropriata).

Il contenitore più esterno verrà utilizzato principalmente per scopi posizionali e di visualizzazione, mentre il contenitore successivo viene utilizzato per decorare il widget con un'immagine di sfondo. Il contenitore esterno è anche necessario per aggiungere i controlli in modo che appaiano sopra il contenuto correttamente in IE.

Il contenitore più interno è l'elemento che verrà utilizzato per visualizzare le immagini. A questo elemento viene assegnata la classe js-disabled che verrà utilizzata esclusivamente per i visitatori che hanno JavaScript disabilitato. Useremo questa classe per ridurre ciascuna delle immagini con CSS in modo che siano tutte visibili.

Le immagini hanno tutte una dimensione uniforme e i contenitori saranno dimensionati per adattarli in modo abbastanza ordinato. La dimensione dell'immagine viene anche utilizzata nello script che aggiungeremo; Evidenzierò specificamente dove questi riferimenti si verificano ma dovresti sapere che se desideri utilizzare immagini di dimensioni diverse, lo script e la dimensione dei contenitori dovranno essere regolati di conseguenza.


Disegnare il widget

Dopo il collegamento a jQuery, abbiamo un elemento script personalizzato con jQuery document.ready scorciatoia, in attesa che aggiungiamo il codice che darà vita al widget. Tuttavia, prima di farlo, aggiungiamo rapidamente il CSS. In un altro nuovo file nel tuo editor di testo, aggiungi i seguenti selettori e regole di stile:

 / * js-disabled class - imposta le dimensioni dell'immagine in modo che si adattino al visualizzatore * / .js-disabled img width: 100px; altezza: 100px; blocco di visualizzazione; float: sinistra; margine: 30px 0 0;  #outerContainer width: 542px; altezza: 202px; margin: auto; position: relative;  #imageScroller width: 542px; altezza: 202px; position: relative; background: # 000000 url (images / imageScrollerBG.png) no-repeat;  #viewer width: 522px; altezza: 182px; overflow: hidden; margin: auto; position: relative; top: 10px;  #imageScroller a: active, #imageScroller a: visited color: # 000000;  #imageScroller a img border: 0;  #controls width: 534px; altezza: 47px; background: url (images / controlsBG.png) no-repeat; position: absolute; top: 4px; a sinistra: 4px; z-index: 10;  #controls a width: 37px; altezza: 35px; position: absolute; top: 3px;  #controls a: active, #controls a: visited color: # 0d0d0d;  #title color: #ffffff; font-family: arial; font-size: 100%; font-weight: bold; width: 100%; text-align: center; margin-top: 10px;  #rtl background: url (images / rtl.png) no-repeat; a sinistra: 100px;  #rtl: hover background: url (images / rtl_over.png) no-repeat; a sinistra: 99px;  #ltr background: url (images / ltr.png) no-repeat; destra: 100px;  #ltr: hover background: url (images / ltr_over.png) no-repeat; 

Se JavaScript è disabilitato e durante il caricamento della pagina, tutte le immagini saranno visibili

Salva questo come imageScroller.css nella stessa cartella della pagina web. Per prima cosa abbiamo il selettore di classe che si rivolge al nostro js-disabili classe; con queste regole abbiamo semplicemente ridimensionato le immagini in modo che siano abbastanza piccole da accatastarsi l'una accanto all'altra lungo la larghezza del widget. Se JavaScript è disabilitato e mentre la pagina è in fase di caricamento, tutte le immagini saranno visualizzabili - una soluzione di sicurezza molto semplice e rapida, ma non necessariamente a prova di stupidità e certamente non completa. Progressive Enhancement. I valori specificati per la larghezza e l'altezza dovranno variare in base al numero di immagini nel visualizzatore.

Seguendo questo abbiamo i selettori e le regole che modellano il widget e lo fanno funzionare correttamente. La maggior parte del codice qui è puramente a scopo di visualizzazione, immagini di sfondo, colori, ecc. Una regola importante, su cui l'implementazione si basa per funzionare correttamente, è l'impostazione di overflow: nascosta nel contenitore del visualizzatore interno. Ciò nasconderà le immagini che devono ancora essere mostrate e le immagini che sono già state passate attraverso il visualizzatore. In questa fase in cui eseguiremo la pagina, dovremmo vedere qualcosa di simile a questo:

Alcuni dei CSS che imposteremo nel JavaScript in un momento, e alcuni degli elementi che abbiamo scelto come target nel CSS non esistono ancora, ma questo è tutto ciò che deve andare nel file CSS.


Portare il widget alla vita

Nella fase finale di questo tutorial aggiungeremo il JavaScript jQuery-flavored che farà funzionare il widget e creerà il comportamento che desideriamo. All'interno della funzione anonima vuota nella parte inferiore della pagina HTML aggiungi il seguente codice:

 // remove js-disabled class $ ("# viewer"). removeClass ("js-disabled"); // crea un nuovo contenitore per le immagini $ ("
") .attr (" id "," container "). css (position:" absolute "). width ($ (". wrapper "). length * 170) .height (170) .appendTo (" div # visualizzatore "); // aggiungi immagini al contenitore $ (". wrapper "). each (function () $ (this) .appendTo (" div # container ");); // calcola la durata dell'anim in base a numero di immagini (1 secondo per ogni immagine) var duration = $ (". wrapper"). length * 1000; // velocità di archiviazione per la successiva var speed = (parseInt ($ ("div # container"). width ()) + parseInt ($ ("div # viewer"). width ())) / duration; // set direction var direction = "rtl"; // imposta la posizione iniziale e la classe in base alla direzione (direction == "rtl")? $ ("div # container"). css ("left", $ ("div # viewer"). width ()). addClass ("rtl"): $ ("div # container"). css ("left" , 0 - $ ("div # container"). Width ()). AddClass ("ltr");

Prima di tutto rimuoviamo la classe js-disabled dal contenitore del visualizzatore. Successivamente creiamo un nuovo contenitore per contenere tutte le immagini che si trovano all'interno del widget. Il motivo principale per questo è che invece di animare ogni immagine singolarmente, con un numero potenzialmente elevato di animazioni in esecuzione simultaneamente, dobbiamo solo animare un elemento: il contenitore che stiamo creando ora.

La larghezza del nuovo contenitore è impostata sul numero di immagini moltiplicato per la larghezza di ciascuna immagine, che in questo esempio è di 170 pixel. Questo è uno dei bit di codice che ho già detto in precedenza e che è qualcosa che dovrà essere modificato se decidiamo di utilizzare immagini di dimensioni diverse. Anche l'altezza del contenitore è specificatamente impostata all'altezza di ogni immagine.

È utile più tardi nella sceneggiatura sapere alcune cose sulla natura dell'animazione, come la sua velocità, la durata che durerà e la direzione del viaggio, quindi imposteremo una serie di variabili per memorizzare queste informazioni. la durata corrisponderà esattamente a un secondo per immagine e si baserà nuovamente sul numero di immagini trovate nel widget.

La velocità è facile da calcolare, essendo ovviamente la distanza del viaggio divisa per la durata del viaggio. Come riferimento, in questo esempio la velocità esatta dell'animazione sarà di 0,274 pixel per millisecondo. La variabile finale, direction, è una semplice stringa che denota che l'animazione procederà da destra a sinistra, anche se potremmo facilmente cambiarla in ltr se desideriamo.

Infine, impostiamo la posizione di partenza del nuovo contenitore; poiché l'animazione è attualmente impostata su rtl, dobbiamo posizionare il nuovo contenitore dell'immagine in modo che il suo bordo sinistro sia impostato sul lato destro del visualizzatore. Se impostiamo l'animazione su ltr, tuttavia, il bordo destro dell'elemento sarà allineato al bordo sinistro del contenitore. Determiniamo la direzione usando il condizionale ternario JavaScript. Oltre alla sua posizione, diamo anche al nuovo contenitore un nome di classe corrispondente alla sua direzione, che possiamo testare in diversi punti dello script.

Successivamente dovremo definire una nuova funzione per avviare e perpetuare l'animazione. Ci sono diverse volte durante la normale esecuzione dello script che avremo bisogno di iniziare l'animazione, quindi avvolgere questa funzionalità in una funzione che possiamo chiamare quando abbiamo bisogno di aiuto per ridurre la quantità di codice. Aggiungi il seguente codice:

 // funzione animator var animator = function (el, time, dir) // quale direzione scorrere se (dir == "rtl") // aggiungi direction class el.removeClass ("ltr"). addClass ("rtl "); // anima il el el.animate (left: "-" + el.width () + "px", time, "linear", function () // reset container position $ (this) .css ( left: $ ("div # imageScroller"). width (), right: ""); // riavvia l'animatore dell'animazione ($ (this), duration, "rtl"); // nasconde i controlli se visibili ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;);  else // aggiungi direction class el.removeClass ("rtl"). addClass ("ltr"); // anima il el el.animate (left: $ ("div # viewer"). width () + "px", time, "linear", function () // reset container position $ (this). css (left: 0 - $ ("div # container"). width ()); // riavvia l'animatore dell'animazione ($ (this), duration, "ltr"); // nasconde i controlli se visibili ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;); 

La funzione animatore accetta tre argomenti; l'elemento da animare, il tempo di esecuzione dell'animazione e la direzione in cui l'elemento deve essere animato. La funzione è suddivisa in due blocchi distinti, uno per l'animazione rtl e l'altro per ltr.

All'interno di ciascun blocco del condizionale aggiorniamo il nome della classe del contenitore dell'immagine per riflettere la direzione corrente nel caso in cui la direzione sia cambiata (questa è una delle interazioni avviate dal visitatore).

Quindi definiamo l'animazione, spostando il contenitore dell'immagine più per ltr o meno per rtl la larghezza del contenitore dell'immagine, dandogli l'impressione di scorrere attraverso il visualizzatore. Sfortunatamente non possiamo usare le animazioni lente, normali o veloci, perché anche l'impostazione lenta limita l'animazione a un tempo di esecuzione totale di soli 600 millisecondi, il che è troppo veloce anche per il piccolo numero di immagini che stiamo utilizzando in questo esempio.

Specifichiamo la stringa lineare come terzo argomento del metodo animato che è la funzione di andamento da utilizzare e imposta l'animazione per procedere ad una velocità uniforme dall'inizio alla fine; se non l'avessimo impostato, l'animazione aumenterebbe notevolmente e rallenterebbe rispettivamente all'inizio e alla fine dell'animazione.

Infine aggiungiamo una funzione di callback anonima che verrà eseguita non appena termina l'animazione; all'interno di questa funzione di callback, restituiamo il contenitore di immagini alla sua posizione di partenza, ricorsivamente chiama nuovamente la funzione animatore passando di nuovo le impostazioni corrette a seconda del ramo del condizionale in esecuzione e nasconde il pannello di controllo se è visibile. Non abbiamo ancora aggiunto il codice che creerà il pannello di controllo, ma abbiamo ancora bisogno di aggiungere questo codice qui per quando lo abbiamo.

Per avviare l'animazione quando la pagina ha un carico, ora dobbiamo chiamare la funzione che abbiamo appena definito; aggiungere la seguente chiamata di funzione:

 // avvia anim animator ($ ("div # container"), durata, direzione);

Tutto ciò che facciamo è chiamare la funzione che passa nell'elemento da animare e le variabili che impostiamo nella prima sezione del codice. Se eseguiamo la pagina ora, dovremmo scoprire che l'animazione inizia non appena la pagina è caricata e continua indefinitamente, come mostrato (tipo di) nella seguente schermata:


Aggiunta di alcune interazioni

Ora siamo nella fase in cui disponiamo delle funzionalità principali del widget e possiamo iniziare ad aggiungere l'interattività aggiuntiva che lo renderà coinvolgente. Dopo la chiamata alla funzione animatore, aggiungi il seguente codice:

 // pause su mouseover $ ("a.wrapper"). live ("mouseover", function () // stop anim $ ("div # container"). stop (true); // mostra i controlli ($ (" div # controls "). length == 0)? $ ("

Come indica il commento, questo gestore di eventi interromperà l'animazione quando il visitatore posiziona il puntatore su una delle immagini all'interno del widget.

Usiamo il metodo live jQuery (nuovo a 1.3!) Per collegare il gestore agli elementi e specificare una funzione anonima da eseguire quando si verifica l'evento.

All'interno di questa funzione, per prima cosa interrompiamo l'animazione usando il metodo jQuery stop, trasmettendo un valore booleano reale come argomento. Questo argomento cancellerà la coda di animazione se esiste; non dovrebbe farlo, poiché dovrebbe esserci sempre un'animazione alla volta, ma è utile usare questo argomento per ogni evenienza.

Controlliamo se il pannello di controllo esiste già e a condizione che non creiamo un nuovo elemento div, diamo un id in modo che raccolga le nostre regole di stile e lo appenda al contenitore esterno. Usiamo quindi il metodo css di jQuery per impostare l'opacità in modo cross-browser per evitare di dover indirizzare browser diversi con il nostro CSS e far scorrere i controlli verso il basso in posizione.

Creiamo anche alcuni collegamenti e li aggiungiamo al pannello di controllo; questi collegamenti fungeranno da pulsanti che consentono al visitatore di cambiare la direzione in cui le immagini si muovono. Aggiungiamo gestori per questi pulsanti in un attimo. Infine, otteniamo il contenuto dell'attributo titolo del collegamento wrapper che ha attivato l'evento mouseover e creato un nuovo elemento paragrafo con il suo testo interno impostato sul titolo. Facciamo molto affidamento sul collegamento condizionale ternario JavaScript in questa sezione di codice in quanto fornisce un meccanismo eccellente solo per la creazione e l'aggiunta di elementi se non esistono già.

Potresti anche aver notato che impostiamo una variabile per contenere il contenuto dell'attributo title dell'attuale trigger, ci si potrebbe chiedere perché non usiamo il seguente codice:

 // aggiungi p se non esiste, aggiornalo se lo fa ($ ("p # title"). length == 0)? $ ("

") .attr (" id "," title "). text ($ (this) .attr (" title ")). appendTo (" div # controls "): $ (" p # title "). text (titolo );

La ragione di ciò è che non vi è alcuna ambiguità su cosa si riferisca a $ (questo). L'uso del codice sopra riportato funziona, ma genera errori, che sebbene non fatali, non sono comunque così rassicuranti per i potenziali utenti del widget. L'uso della variabile assicura semplicemente che questi errori siano evitati. Il pannello di controllo, quando visibile, appare come nella seguente schermata:

Seguendo il mouseover l'animazione verrà interrotta; possiamo riavviarlo facilmente usando un gestore di eventi mouseout, che dovremmo aggiungere successivamente:

 // restart on mouseout $ ("a.wrapper"). live ("mouseout", function (e) // nasconde i controlli se non passa il mouse su di essi (e.relatedTarget == null)? null: (e.relatedTarget. id! = "controls")? $ ("div # controls"). slideUp ("slow"). remove (): null; // calcola la distanza totale di viaggio var totalDistance = parseInt ($ ("div # container") .width ()) + parseInt ($ ("div # viewer"). width ()); // calcola la distanza a sinistra per percorrere var distanceLeft = ($ ("div # container"). hasClass ("ltr")) ? totalDistance - (parseInt ($ ("div # container"). css ("left")) + parseInt ($ ("div # container"). width ())): totalDistance - (parseInt ($ ("div # viewer "). width ()) - (parseInt ($ (" div # container "). css (" left ")))); // new duration è distance left / speed) var newDuration = distanceLeft / speed; // restart anim animator ($ ("div # container"), newDuration, $ ("div # container"). attr ("classe")); );

Ancora una volta usiamo il metodo live di jQuery, ma questa volta passiamo anche l'oggetto evento raw alla nostra funzione di callback anonimo. Utilizziamo subito questo oggetto per vedere se il puntatore si è spostato sul pannello di controllo. In caso contrario, nascondiamo i controlli, ma in caso contrario, non facciamo nulla e procediamo con il riavvio dell'animazione. Notate come usiamo un ternario annidato che è equivalente a un altro se condizionale.

Lo scopo principale della funzione anonima è di riavviare l'animazione, ma prima di farlo è necessario calcolare la durata dell'animazione; non possiamo hardcode il valore perché il contenitore di immagini si sarà spostato. La durata iniziale è stata impostata su 1 secondo per ciascuna immagine, in questo esempio 5 secondi. Se è rimasta solo un'immagine visibile nel visualizzatore e impostiamo nuovamente l'animazione su 5 secondi, l'animazione procederà nettamente più lentamente.

Iniziamo a capire quale sia la distanza totale percorsa dal contenitore di immagini in un'animazione completa. Quindi elaboriamo quanto della distanza completa deve ancora essere percorsa. Dovremo fare un calcolo diverso a seconda che l'animazione stia accadendo da sinistra a destra o viceversa, quindi utilizziamo nuovamente il condizionale ternario.

Se l'animazione si verifica da sinistra a destra, la distanza da percorrere è l'attributo di stile sinistro del contenitore dell'immagine (ottenuto utilizzando il metodo jQuery css) aggiunto alla larghezza del contenitore dell'immagine, sottratto dalla distanza totale. Tuttavia, se il contenitore dell'immagine si sposta da destra a sinistra, la distanza da percorrere è la larghezza del contenitore dell'immagine meno l'attributo stile sinistro, sottratto dalla distanza totale. I metodi jQuery di larghezza e css restituiscono valori di stringa, quindi utilizziamo la funzione parseInt di JavaScript per convertirli in valori numerici.

La nuova durata dell'animazione viene quindi calcolata dividendo la distanza da percorrere per la velocità che abbiamo elaborato proprio all'inizio del codice. Una volta ottenuta questa figura, possiamo chiamare di nuovo la funzione animatore passando i parametri richiesti, facendo ripartire l'animazione da dove si è fermata, nella stessa direzione di viaggio.


Cambiando direzione

Per la parte finale del nostro script possiamo aggiungere i gestori per i collegamenti nel pannello di controllo usato per cambiare la direzione dell'animazione. Subito dopo il codice che abbiamo appena aggiunto, inserisci il seguente codice:

 // gestore per il tasto ltr $ ("# ltr"). live ("click", function () // stop anim $ ("div # container"). stop (true); // scambia i nomi delle classi $ (" div # container "). removeClass (" rtl "). addClass (" ltr "); // calcolo della distanza totale di viaggio var totalDistance = parseInt ($ (" div # container "). width ()) + parseInt ($ ( "div # viewer"). width ()); // calcolo della distanza rimanente var distanceLeft = totalDistance - (parseInt ($ ("div # container"). css ("left")) + parseInt ($ ("div # container "). width ())); // new duration è distance left / speed) var newDuration = distanceLeft / speed; // restart anim animator ($ ("div # container"), newDuration, "ltr"); );

Questa funzione, attivata quando si fa clic sul pulsante sinistro-destro, è relativamente semplice e contiene un codice molto simile a quello che abbiamo già utilizzato; per prima cosa interrompiamo l'animazione corrente (riprenderà quando il visitatore sposta il puntatore sul pannello di controllo), quindi scambia il nome della classe in modo che corrisponda alla nuova direzione di viaggio. Quindi elaboriamo la nuova durata dell'animazione nello stesso modo in cui lo abbiamo fatto in precedenza, prima di chiamare finalmente la nostra funzione animatore. Questo è solo il gestore per il pulsante ltr; il gestore del pulsante rtl è quasi identico, ma utilizza il calcolo corretto per la direzione opposta del viaggio:

 // gestore per il tasto rtl $ ("# rtl"). live ("click", function () // stop anim $ ("div # container"). stop (true); // scambia i nomi delle classi $ (" div # container "). removeClass (" ltr "). addClass (" rtl "); // calcola la distanza totale di viaggio var totalDistance = parseInt ($ (" div # container "). width ()) + parseInt ($ ( "div # viewer"). width ()); // calcolo della distanza rimanente var distanceLeft = totalDistance - (parseInt ($ ("div # viewer"). width ()) - (parseInt ($ ("div # container") ) .css ("left")))); // new duration è distance left / speed) var newDuration = distanceLeft / speed; // restart anim animator ($ ("div # container"), newDuration, "rtl"); );

Questo è ora tutto il codice che dobbiamo scrivere, se si esegue la pagina in un browser a questo punto, si dovrebbe trovare che il widget funziona come previsto.


Sommario

In questo tutorial abbiamo creato un widget divertente e interattivo per la visualizzazione di una serie di immagini e potrebbe essere utilizzato per visualizzare i loghi dei produttori di prodotti che vendi o dei loghi dei software che tu consigli o di qualsiasi altra cosa desideri. Ci siamo concentrati principalmente sugli aspetti di animazione e interazione del widget, ma abbiamo anche considerato cose come fornire un fallback di base nel caso in cui JavaScript sia disabilitato nel browser.