Hammer.js è una libreria Javascript che permette di interagire con i contenuti Web con le azioni classiche di un touch scree: tap, double tap, hold, drag e pinch.
Tipicamente i nostri siti non intercettano tutti gli eventi che vengono scatenati sullo schermo di smartphone e tablet, fatta eccezione per il 'tap' e in questo articolo vedremo come Hammer.js si propone di semplificare la gestione delle gesture più comuni.
I test sono stati effettuati su iPad e iPhone 4 con iOS 5, Samsung Galaxy S (Android 2.3.3). Chi non ha a disposizione un dispositivo simle, può comunque utilizzare il mouse per emulare il contatto del dito.
La documentazione al momento è piuttosto limitata, ma include alcuni esempi che illustrano come utilizzarla. In sostanza le operazioni da fare, per iniziare con un primo esempio, non sono troppo complesse, si creano:
- un'istanza Hammer su un oggetto DOM
- una funzione di callback per qualsiasi gesto si voglia supportare
Hammer.js come plugin di jQuery
È possibile utilizzare Hammer.js autonomamente oppure come plugin di jQuery. Questo ci semplifica semplifica la gestione degli eventi, che vediamo in un semplice esempio in cui spostiamo alcuni elementi div
.
Come si vede in figura, nell'esempio sarà possibile trascinare questi elementi colorati dietro una maschera (con il logo di HTML.it trasparente) attraverso cui si vedranno anche dopo essere stati spostati.
Anzitutto includiamo nella pagina la libreria e le dipendenze:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/hammer.js"></script>
<script src="js/jquery.hammer.js"></script>
Abbiamo il solito jQuery, che ci semplificherà la vita con gli event handler e la nostra libreria. Includiamo anche jquery.hammer.js
che non aggiunge di nuovo, ma garantisce solamente l'inizializzazione di Hammer.JS
.
Aggiungiamo ora una sezione style
, che permetterà non solo di stilizzare le nostre colonne,
ma soprattutto per sfruttare le nuove funzionalità di CSS3. Riporto qui solo la parte condivisa fra tutte le colonne:
/* stile e animazione condivisa delle colonne */
.col {
height:120px; position:absolute; top:10px;
-webkit-transition: all 225ms cubic-bezier(0.545, 0.165, 0.835, 0.425);
-moz-transition: all 225ms cubic-bezier(0.545, 0.165, 0.835, 0.425);
-ms-transition: all 225ms cubic-bezier(0.545, 0.165, 0.835, 0.425);
-o-transition: all 225ms cubic-bezier(0.545, 0.165, 0.835, 0.425);
transition: all 225ms cubic-bezier(0.545, 0.165, 0.835, 0.425);
}
Questo invece sarà il corpo del nostro documento. Una semplice lista di elementi div
.
<div id="wrap">
<div class="mask"></div>
<div id="blocks">
<div class="col col1" ></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
<div class="col col6"></div>
</div>
</div>
Gestire gli eventi con Hammer.js
La gestione degli eventi con jQuery è la parte più semplice poiché non siamo obbligati a scrivere righe di codice per gestire cose come il drag
. L'utilizzo di Hammer.Js in modalità autonoma, invece, prevede una gestione più articolata degli eventi.
Ecco lo stesso handler
visto prima come libreria autonoma, e successivamente come plugin di jQuery.
//Hammer.JS in modalità autonoma
var hammer = new Hammer(document.getElementById(".mask"));
hammer.ondragstart = function(ev) {...};
hammer.ondrag = function(ev) {...};
hammer.ondragend = function(ev) {...};
//Hammer.JS come plugin di jQuery
$(".mask")
.hammer({
// opzioni...
}).bind("drag", function(ev) {
console.log(ev);
});
//Nel nostro caso avremo..
$(".col").hammer({prevent_default:true}).bind("drag", function(ev) {...});
Sembra eviente che l'utilizzo come plugin di jQuery sia più semplice.
Tutti gli eventi ritornano:
originalEvent
: evento originale del DOM.position
: posizione x e j dell'oggetto che ha scetenato l'evento.touches
: array di tocchi, contiene un oggetto con x e y per ogni dito.
Il nostro codice jQuery, così compatto, ci permette di aggiungo un listener per la funzione di drag
per tutte le colonne, ovvero a tutti gli elementi di classe '.col
'.
L'opzione di configurazione prevent_default
migliori l'affidabilità della gestione del trascinamento sui device, in quanto inibisce le azioni di default del browser, specialmente utile quando prevediamo trascinamenti verticali.
La funzione di callback che definiamo si basa sull'evento ritornato da Hammer.js per determinare se l'elemento è stato trascinato verso il basso e, in caso affermativo, aggiungiamo lo stile alla colonna in modo da innescare l'effetto di transizione CSS3. Vediamo come:
$(".mask").hammer({prevent_default:true}).bind("drag", function(ev) {
// controllo la posizione sulla machera per determinare quale elemento sta per esser spostato
if (ev.direction == "up") {
if (ev.position.x > 26 && ev.position.x < 130) {
$(".col1").removeClass("col-anim");
}
}
});
Lavorare con una maschera
La gestione del trascinamento diventa più complessa quando gli elementi della colonna sono dietro una maschera. Questo significa che i gli eventi touch
non vengono eseguiti sulle colonne. Di conseguenza, bisogna gestire l'evento di trascinamento sull'intera maschera, controllando la posizione del dito in quel momento.
Poiché ad ogni evento Hammer.js restituisce un oggetto, con posizione x
e y
, possiamo determinare la colonna su cui attivare il trascinamento in base alla posizione del gesto.
In questo caso stiamo solo aggiungendo e rimuovendo classi CSS per avviare una transizione CSS dal basso vero l'alto e viceversa. Potremmo sviluppare soluzioni più avanzate utilizzando Hammer.js. Catturare l'inizio del trascinamento e gli eventi finali come la gestione della direzione del trascinamento per consentire un controllo più diretto della destinazione dell'oggetto.
Ma questa semplice soluzione, permette di verificare le potenzialità di questa libreria che, se lo sviluppo proseguirà con questo ritmo, potrebbe affiancarsi o competere con jQuery Mobile.
Link utili