
In questi giorni ho aiutato un amico alle prese con un sito web a pagina singola e prendendo spunto dal sito vanadiumjs.com ho voluto implementare lo scroll automatico e animato. Dopo un giretto sul web ho trovato questo interessante script da cui ho imparato un po’ di cose che ti ripropongo.
Il mio non è stato solo uno sfizio: poiché la pagina era molto lunga mi sembrava utile inserire questa funzionalità al fine di evitare all’utente l’utilizzo prolungato della rotellina del mouse per poter scorrere la pagina. Certo, si poteva realizzare tutto con dei link interni di tipo “#id” evitando codice js e plugin jquery. Lo abbiamo fatto ugualmente perché la pagina era solo una e un po’ di dinamismo non guasta mai!
La proprietà “scrollTop”. La utiliziamo per delineare le caratteristiche dell’animazione all’interno del metodo $.animate(). Questa proprietà deve essere impostata con un valore intero pari alla distanza (in pixel) tra l’inizio della pagina e la posizione di destinazione.
Il plugin “easing”. Non è fondamentare per realizzare lo scroll animato in quanto all’animazione ci pensa già il metodo $.animate(). Questo plugin ci serve per aggiungere a jquery altri tipi di animazione. Per saperne di più visita la pagina del plugin in cui potrai provare tutte le animazioni.
Animazione “easeInOutQuad”. Il vero motivo per cui utilizziamo il plugin “easing” è per sfruttare l’animazione “easeInOutQuad” (uguale a quella di vanadiumjs.com) molto adatta per uno scroll animato: parte lenta, scorre veloce, e inizia a rallentare prima di arrivare sulla destinazione del link.
Aspetti positivi
Nessun problema se javascript è disabilitato. Poiché utiliziamo dei link interni (o ancore) per chiamare l’animazione sullo scroll, in caso di javascript disabilitato questi link funzioneranno comunque e faranno in modo di proiettare l’utente sul blocco con l’id specificato nell’attributo href.
Normale scroll della pagina inalterato. Nonostante l’animazione, il normale scroll della pagina non viene alterato in alcun modo e la barra di scorrimento continua a funzionare come ci si aspetterebbe.
Codice riusabile. Il codice javascript (e jquery) non dipende dal numero di link che devono avviare uno scroll animato. Infatti l’unica operazione richiesta è quella di specificare la classe comune ai link che avviano lo scroll animato.
Al lavoro!
RISULTATO FINALE: http://test.jblog.it/autoscroll/
DOWNLOAD: http://download.jblog.it/autoscroll.zip
1. Includere jquery e jquery.easing
<head> ... <script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript" src="jquery.easing.1.3.js"></script> ... </head>
2. Attribuire una la stessa classe a tutti i link per lo scroll animato
<!-- la classe comune è "scrollToBlock" --> <a href="#blocco1" class="scrollToBlock">Blocco 1</a> <a href="#blocco2" class="scrollToBlock">Blocco 2</a> <a href="#blocco3" class="scrollToBlock">Blocco 3</a> <a href="#blocco4" class="scrollToBlock">Blocco 4</a> <a href="#blocco5" class="scrollToBlock">Blocco 5</a>
3. Copiare il blocco di codice per lo scroll animato
Anche se mi sembra superfluo dirlo, il seguente blocco di codice deve essere inserito fra i tag <head></head>.
<script type="text/javascript">
$(document).ready(function(){
$('.scrollToBlock').click(function(){
// recupera l'id e la distanza del blocco verso cui eseguire lo scroll
var position = $( $(this).attr("href") ).offset().top;
// ANIMAZIONE
// (in alcuni browser funziona "body" in altri "html")
// not(:animated) evita che un altro click su un'altra voce del menù abbia effetto quando il precedente scroll non si è concluso
$("body:not(:animated), html:not(:animated)").animate(
{ scrollTop:position }, // parametri dell'animazione
1000, // durata animazione (in millisecondi)
'easeInOutQuad'); // animazione (del plugin "jquery.easing")
// evita che la url venga "sporcata" con l'aggiunta di "#bloccoX"
return false;
});
});
</script>
4. Impostare la classe dei link che avviano lo scroll animato
<script type="text/javascript">
$(document).ready(function(){
$('INSERIRE QUI la classe').click(function(){
...
5. Decidere la durata dell’animazione (in millisecondi)
...
$("body:not(:animated), html:not(:animated)").animate(
{ scrollTop:position }, // parametri dell'animazione
1000, // durata animazione (in millisecondi)
'easeInOutQuad'); // animazione (del plugin "jquery.easing")
...
6. Decidere l’animazione del plugin “easing”
Nella pagina del plugin puoi trovare l’elenco completo delle animazioni e la dimostrazione di ciascuna di esse.
...
$("body:not(:animated), html:not(:animated)").animate(
{ scrollTop:position }, // parametri dell'animazione
1000, // durata animazione (in millisecondi)
'easeInOutQuad'); // animazione (del plugin "jquery.easing")
...
7. Attribuire un id diverso a ciascun blocco di destinazione
<div class="block" id="blocco1"> <h2>Blocco 1</h2> <p>Lorem ipsum...</p> </div> <div class="block" id="blocco2"> <h2>Blocco 2</h2> <p>Sed ut perspiciatis...</p> </div> <div class="block" id="blocco3"> <h2>Blocco 3</h2> <p>Lorem ipsum...</p> </div> <div class="block" id="blocco4"> <h2>Blocco 4</h2> <p>Sed ut perspiciatis...</p> </div> <div class="block" id="blocco5"> <h2>Blocco 5</h2> <p>Lorem ipsum...</p> </div>
8. Attribuire l’id di ciascun blocco di destinazione al relativo link
<!-- la classe comune è "scrollToBlock" --> <a href="#blocco1" class="scrollToBlock">Blocco 1</a> <a href="#blocco2" class="scrollToBlock">Blocco 2</a> <a href="#blocco3" class="scrollToBlock">Blocco 3</a> <a href="#blocco4" class="scrollToBlock">Blocco 4</a> <a href="#blocco5" class="scrollToBlock">Blocco 5</a>
Animazioni multiple
Vorrei spendere qualche parola in più sulla riga seguente per dire come ci si arriva a scriverla:
$("body:not(:animated), html:not(:animated)").animate(...);
PROBLEMA 1
Teoricamente si dovrebbe scrivere:
$("body").animate(...);
perché lo scroll riguarda il tag <body>.
Poiché su alcuni browser lo scroll della pagina è inteso su <html> e non su <body>, per supportarli entrambi è necessario scrivere:
$("html,body").animate(...);
In questo modo lo scroll funzionerà sia con i browser che lo intendono su <body> sia su quelli che lo intendono su <html>.
PROBLEMA 2
Se durante uno scroll si clicca su un’altro link prima che lo scroll precedente sia completato, il secondo scroll NON inizia subito ma “si mette in coda” e inizierà quando lo scroll precedente sarà stato completato.
Ora, immaginate che durante uno scroll si clicchi su più di un link: una volta completato lo scroll inizieranno una serie di scroll corrispondenti ai click precedenti.
Questa situazione non è accettabile per vari motivi, ma soprattutto perché non ha alcun senso e alcuna utilità sia per l’utente che per il web designer.
La soluzione è quella di bloccare la partenza di uno scroll automatico prima che il precedente sia stato completato.
La pseudo-classe :not() serve per escludere dalla selezione tutti gli elementi con determinate caratteristiche che possono essere “disabilitato”, “nascosto”, “attivo”, “animato”, ecc.
In particolare a noi serve che la pseudo-classe :not() escluda gli elementi animati, identificati dalla pseudo-classe :animated: in questo caso gli elementi da escludere (quando sono animati) sono <html> e <body>.
Per escludere un elemento animato si scrive:
$("elemento:not(:animated)")...
Quindi, per escludere <html> e <body> quando sono animati:
$("body:not(:animated), html:not(:animated)")...
La posizione di arrivo
Come avrai notato lo scroll automatico arriva precisamente sull’elemento.
Questo può non essere bellissimo da vedere poiché il blocco di arrivo risulta appiccicato al bordo superiore del browser.
Per fare in modo che il blocco di arrivo abbia un certo margine dal bordo del browser bisogna sottrarre alcuni pixel dalla posizione calcolata.
Individua la riga:
var position = $( $(this).attr("href") ).offset().top;
e modificala in:
var position = $( $(this).attr("href") ).offset().top ( - XX );
dove “XX” sono i pixel di margine dal bordo superiore del browser.
Foto | http://www.flickr.com/photos/jurvetson/17095584/


