Eventi di tocco personalizzati in HTML5

Matteo Casati

di ,

Nello script precedente abbiamo introdotto gli eventi di tipo touch previsti dal W3C per gestire l'interazione dell'utente con il dispositivo attraverso il tocco.
Intercettando gli eventi di base touchstart, touchend e touchmove e combinandoli opportunamente con della semplice logica JavaScript è possibile creare degli eventi di tocco personalizzati, come ad esempio:

  • tap: l'equivalente del click del mouse, scatenato toccando e rilasciando il dito in un punto del display;
  • longTap: un tocco prolungato del dito sul display;
  • swipe: quando il dito viene strisciato sul display (in qualsiasi direzione);
  • swipeLeft: il dito viene strisciato sul display verso sinistra
  • swipeRight: il dito viene strisciato sul display verso destra
  • swipeUp: il dito viene strisciato sul display verso l'alto
  • swipeDown: il dito viene strisciato sul display verso il basso

L'esempio seguente mostra tutto il codice necessario per intercettare il tocco sul documento, registrare gli eventi personalizzati descritti sopra e intercettarli per un elemento del DOM:

<!doctype html>
<html>
    <head>
        <title>Touch Events</title>  
        <style>
            div#touchArea { padding: 15px; background: #c00; color: #fff; font-size: 18pt; }
        </style>
        <script>
            
            function log(event)
            {
                touchArea.innerHTML = event.type;
            };
            
            function fireEvent(element, event)
            {
                var e = document.createEvent("HTMLEvents"); // use HTML event module; alternatives: "UIEvents"/initUIEvent(), "MouseEvents"/initMouseEvent(), etc.  
                e.initEvent(event, true, true);
                return !element.dispatchEvent(e);
            };
            
            var touch = {}; // start, x1, y1, x2, y2, doubleTap, target
            var tapTimeout;
            function touchHandler(event)
            {
                var now = Date.now();
                switch (event.type)
                {
                    case "touchstart":
                        if (touch.start && now - touch.start < 250)
                            touch.doubleTap = true;                                                   
                        touch.start = Date.now();
                        touch.x1 = event.touches[0].pageX;
                        touch.y1 = event.touches[0].pageY;
                        touch.target = ("tagName" in event.touches[0].target) ? event.touches[0].target : event.touches[0].target.parentNode;   // if text node target is parent
                        break;
                    
                    case "touchmove":
                        touch.x2 = event.touches[0].pageX;
                        touch.y2 = event.touches[0].pageY;
                        break;
                    
                    case "touchend":
                        if (touch.doubleTap) 
                        {
                            window.clearTimeout(tapTimeout);
                            fireEvent(touch.target, "doubleTap");
                            touch = {};
                            return;
                        }
                        if (touch.x2 > 0 || touch.y2 > 0)
                        {
                            var deltaX = touch.x1 - touch.x2;
                            var deltaY = touch.y1 - touch.y2;
                            if (Math.abs(deltaX) > 30 || Math.abs(deltaY) > 30) // min 30px
                            {
                                fireEvent(touch.target, "swipe"); // generic swipe
                                if (Math.abs(deltaX) >= Math.abs(deltaY)) // horizontal
                                {
                                    if (deltaX > 0)
                                        fireEvent(touch.target, "swipeLeft");
                                    else
                                        fireEvent(touch.target, "swipeRight");
                                }
                                else // vertical
                                {
                                    if (deltaY > 0)
                                        fireEvent(touch.target, "swipeUp");
                                    else
                                        fireEvent(touch.target, "swipeDown");
                                }
                                touch = {};
                                return;
                            }
                        }                        
                        if (touch.start && now - touch.start > 500) // min 500msec
                        {
                            fireEvent(touch.target, "longTap");
                            touch = {};
                            return;
                        }                                                
                        tapTimeout = window.setTimeout(function() { fireEvent(touch.target, "tap"); }, 250);   // avoid conflict with doubleTap
                        break;
                    
                    case "touchcancel":
                        touch = {};
                        break;
                    
                    default: // not a touch event
                        return;
                } 
            };
                        
            var touchArea; 
            document.addEventListener("DOMContentLoaded", function()
            {
                document.addEventListener("touchstart", touchHandler, true);
                document.addEventListener("touchmove", touchHandler, true);
                document.addEventListener("touchend", touchHandler, true);
                document.addEventListener("touchcancel", touchHandler, true);
                
                touchArea = document.getElementById("touchArea");
                touchArea.addEventListener("tap", log);
                touchArea.addEventListener("longTap", log);
                touchArea.addEventListener("doubleTap", log);
                touchArea.addEventListener("swipe", log);
                touchArea.addEventListener("swipeLeft", log);
                touchArea.addEventListener("swipeRight", log);
                touchArea.addEventListener("swipeUp", log);
                touchArea.addEventListener("swipeDown", log);
                
            }, false);
            
        </script>        
    </head>
    <body>
        <div id="touchArea">Touch me!</div>        
    </body>
</html>

Nota: molte librerie specifiche per browser mobile (jQuery Mobile, jqMobi, Zepto, ecc.) forniscono implementazioni di eventi personalizzati analoghe a quella mostrata nello snippet precedente.

Link e riferimenti utili

Script #26, "Gestire gli eventi di tipo touch con HTML5"
http://www.html5italia.com/script/26/Gestire-Eventi-Tipo-Touch-HTML5.aspx

Le specifiche del W3C per gli eventi di tocco (Touch Events)
http://www.w3.org/TR/touch-events/

Il nostro speciale sullo sviluppo web mobile
http://www.aspitalia.com/focuson/1267/Speciale-Web-Mobile-Costruire-Applicazioni-ASP.NET-JQuery-Mobile.aspx

Commenti

Eventi di tocco personalizzati in HTML5 (#27) 1010 2
| Condividi su: Twitter, Facebook, LinkedIn, Google+

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi

Script via e-mail

Iscriviti alle nostre newsletter tematiche unoscript@lgiorno per ricevere gli script via e-mail.

Iscrivi subito! »»»

In primo piano
Media
In evidenza
MISC