Sviluppo web multi-touch

Boris Smus
Boris Smus

introduzione

I dispositivi mobili come smartphone e tablet di solito sono dotati di uno schermo capacitivo sensibile al tocco per acquisire le interazioni effettuate con le dita dell'utente. Man mano che il Web mobile si evolve per abilitare applicazioni sempre più sofisticate, gli sviluppatori web hanno bisogno di un modo per gestire questi eventi. Ad esempio, quasi tutti i giochi ad alto ritmo richiedono la pressione di più pulsanti contemporaneamente, il che, nel contesto di un touchscreen, implica la funzionalità multi-touch.

Apple ha introdotto l'API degli eventi touch in iOS 2.0. Android ha superato questo standard di fatto e ha colmato il divario. Di recente, un gruppo di lavoro di W3C si è riunito per lavorare a queste specifiche degli eventi touch.

In questo articolo esamineremo l'API per gli eventi touch fornita dai dispositivi iOS e Android, nonché Chrome per desktop su hardware che supporta il tocco, e esplorerò i tipi di applicazioni che puoi creare, presenterò alcune best practice e tratterò tecniche utili che semplificano lo sviluppo di applicazioni compatibili con il tocco.

Eventi touch

Nelle specifiche vengono definiti tre eventi di tocco di base e implementati in modo ampio su tutti i dispositivi mobili:

  • touchstart: viene posizionato un dito su un elemento DOM.
  • touchmove: un dito viene trascinato lungo un elemento DOM.
  • touchend: viene rimosso un dito da un elemento DOM.

Ogni evento tocco include tre elenchi di tocchi:

  • tocchi: un elenco di tutte le dita attualmente visualizzate sullo schermo.
  • targetTouches: un elenco di dita sull'elemento DOM corrente.
  • changedTouches: un elenco di dita coinvolte nell'evento corrente. Ad esempio, in un evento di touchpoint, questo sarà il dito che è stato rimosso.

Questi elenchi sono composti da oggetti che contengono informazioni sul tocco:

  • identifier: un numero che identifica in modo univoco il dito corrente nella sessione di tocco.
  • target: l'elemento DOM target dell'azione.
  • Coordinate cliente/pagina/schermo: il punto sullo schermo in cui è avvenuta l'azione.
  • Coordinate del raggio e Angolo di rotazione: descrivi l'ellisse che si avvicina alla forma del dito.

App compatibili con il tocco

Gli eventi touchstart, touchmove e touchend offrono un set di funzionalità sufficientemente completo da supportare praticamente qualsiasi tipo di interazione basata sul tocco, inclusi tutti i consueti gesti multi-touch come pizzico, zoom, rotazione e così via.

Questo snippet ti consente di trascinare un elemento DOM con il tocco con un dito:

var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // If there's exactly one finger inside this element
  if (event.targetTouches.length == 1) {
    var touch = event.targetTouches[0];
    // Place element where the finger is
    obj.style.left = touch.pageX + 'px';
    obj.style.top = touch.pageY + 'px';
  }
}, false);

Di seguito è riportato un esempio che mostra tutti i tocchi attuali sullo schermo. È utile solo per avere l'impressione della reattività del dispositivo.

Rilevamento delle dita.
// Setup canvas and expose context via ctx variable
canvas.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.touches.length; i++) {
    var touch = event.touches[i];
    ctx.beginPath();
    ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true);
    ctx.fill();
    ctx.stroke();
  }
}, false);

Demo

Esistono già diverse demo multi-touch interessanti, come questa demo di disegni su tela di Paul Ireland e altri.

Screenshot del disegno

E Browser Ninja, una demo tecnologica con un clone di Fruit Ninja che utilizza trasformazioni e transizioni CSS3, oltre a canvas:

Browser ninja

Best practice

Impedisci lo zoom

Le impostazioni predefinite non funzionano molto bene per il multi-touch, poiché scorrimenti e gesti sono spesso associati al comportamento del browser, ad esempio lo scorrimento e lo zoom.

Per disattivare lo zoom, configura l'area visibile in modo che non sia scalabile per l'utente utilizzando il seguente meta tag:

<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no>

Consulta questo articolo sull'HTML5 per dispositivi mobili per ulteriori informazioni sull'impostazione dell'area visibile.

Impedisci lo scorrimento

Alcuni dispositivi mobili hanno comportamenti predefiniti per touchmove, ad esempio l'effetto classico di overscroll per iOS, che causa il rimbalzo della visualizzazione quando lo scorrimento supera i limiti dei contenuti. Questo può creare confusione in molte applicazioni multi-touch e può essere facilmente disattivato:

document.body.addEventListener('touchmove', function(event) {
  event.preventDefault();
}, false); 

Esegui il rendering con attenzione

Se stai scrivendo un'applicazione multi-touch che prevede gesti con più dita complessi, fai attenzione a come reagisci agli eventi di tocco, poiché ne gestirai così tanti contemporaneamente. Considera l'esempio della sezione precedente che traccia tutti i tocchi sullo schermo. Puoi disegnare non appena c'è un input tocco:

canvas.addEventListener('touchmove', function(event) {
  renderTouches(event.touches);
}, false);

Tuttavia, questa tecnica non ridimensiona con il numero di dita sullo schermo. Potresti invece tracciare tutte le dita ed eseguire il rendering in un loop per ottenere prestazioni di gran lunga migliori:

var touches = []
canvas.addEventListener('touchmove', function(event) {
  touches = event.touches;
}, false);

// Setup a 60fps timer
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

Utilizza targetTouches e ChangeTouches

Ricorda che event.touches è un array di TUTTE le dita a contatto con lo schermo, non solo quelle sul target dell'elemento DOM. Potresti trovare molto più utile usare invece event.targetTouches o event.changedTouches.

Infine, poiché stai sviluppando per il mobile, dovresti conoscere le best practice generali per i dispositivi mobili, illustrate nell'articolo di Eric Bidelman e in questo documento di W3C.

Assistenza per i dispositivi

Sfortunatamente, le implementazioni degli eventi touch variano notevolmente in completezza e qualità. Ho scritto uno script di diagnostica che mostra alcune informazioni di base sull'implementazione dell'API Touch, inclusi gli eventi supportati e la risoluzione dell'attivazione touchmove. Ho testato Android 2.3.3 su Nexus One e hardware Nexus S, Android 3.0.1 su Xoom e iOS 4.2 su iPad e iPhone.

In breve, tutti i browser testati supportano gli eventi touchstart, touchend e touchmove.

La specifica fornisce tre eventi tocco aggiuntivi, ma nessun browser testato li supporta:

  • touchenter: un dito mobile entra in un elemento DOM.
  • touchleave: un dito che si muove lascia un elemento DOM.
  • touchcancel: un tocco è stato interrotto (specifica dell'implementazione).

All'interno di ogni touch list, i browser testati forniscono anche i touch list touchscreen, targetTouches e changedTouches. Tuttavia, nessun browser testato supporta RadiusX, RadiyY o RuandAngle, che specificano la forma del dito che tocca lo schermo.

Durante un movimento touch, gli eventi si attivano circa 60 volte al secondo su tutti i dispositivi testati.

Android 2.3.3 (Nexus)

Il multi-touch Browser Android Gingerbread (testato su Nexus One e Nexus S) non è disponibile. Questo è un problema noto.

Android 3.0.1 (Xoom)

Il browser di Xoom prevede il supporto multi-touch di base, ma funziona solo su un singolo elemento DOM. Il browser non risponde correttamente a due tocchi simultanei su diversi elementi DOM. In altre parole, quanto segue reagirà a due tocchi simultanei:

obj1.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.targetTouches; i++) {
    var touch = event.targetTouches[i];
    console.log('touched ' + touch.identifier);
  }
}, false);

Tuttavia, quanto segue:

var objs = [obj1, obj2];
for (var i = 0; i < objs.length; i++) {
  var obj = objs[i];
  obj.addEventListener('touchmove', function(event) {
    if (event.targetTouches.length == 1) {
      console.log('touched ' + event.targetTouches[0].identifier);
    }
  }, false);
}

iOS 4.x (iPad, iPhone)

I dispositivi iOS supportano completamente il multi-touch, sono in grado di rilevare un bel po' di dita e forniscono un'esperienza tattile molto reattiva nel browser.

Strumenti per sviluppatori

Nello sviluppo per dispositivi mobili, spesso è più facile iniziare a creare prototipi sul computer e poi affrontare le parti specifiche per i dispositivi mobili sui dispositivi che intendi supportare. La tecnologia multi-touch è una di quelle funzionalità difficili da testare su PC, in quanto la maggior parte dei PC non dispone di input tocco.

Eseguire test su dispositivi mobili può allungare il ciclo di sviluppo, poiché ogni modifica deve essere inviata a un server e poi caricata sul dispositivo. Una volta eseguita, non puoi fare molto per eseguire il debug dell'applicazione, in quanto tablet e smartphone non dispongono di strumenti per sviluppatori web.

Una soluzione a questo problema è simulare gli eventi di tocco sulla macchina di sviluppo. Per i singoli tocchi, gli eventi tocco possono essere simulati in base agli eventi del mouse. Gli eventi multi-touch possono essere simulati se hai un dispositivo con input touch, come un moderno Apple MacBook.

Eventi single-touch

Se vuoi simulare eventi single-touch sul desktop, Chrome fornisce l'emulazione degli eventi tocco dagli strumenti per sviluppatori. Apri gli Strumenti per sviluppatori, seleziona l'icona a forma di ingranaggio Impostazioni, quindi "Override" o "Emulazione" e attiva l'opzione "Emula eventi touch".

Per altri browser potresti provare Phantom Limb, che simula gli eventi touch sulle pagine e dà una mano enorme per l'avvio.

È disponibile anche il plug-in jQuery Touchable che unifica gli eventi di tocco e mouse su tutte le piattaforme.

Eventi multi-touch

Per consentire il funzionamento della tua applicazione web multi-touch nel browser sul trackpad multi-touch (ad esempio un Apple MacBook o MagicPad), ho creato il polyfill MagicTouch.js. Cattura gli eventi touch dal trackpad e li trasforma in eventi touch compatibili con gli standard.

  1. Scarica e installa il plug-in npTuioClient NPAPI in ~/Library/Internet Plug-Ins/.
  2. Scarica l'app TongSeng TUIO per MagicPad per Mac e avvia il server.
  3. Scarica MagicTouch.js, una libreria JavaScript per simulare gli eventi di tocco compatibili con le specifiche in base ai callback npTuioClient.
  4. Includi lo script magictouch.js e il plug-in npTuioClient nella tua applicazione nel seguente modo:
<head>
  ...
  <script src="/path/to/magictouch.js"></script>
</head>

<body>
  ...
  <object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
    Touch input plugin failed to load!
  </object>
</body>

Potrebbe essere necessario abilitare il plug-in.

È disponibile una demo dal vivo con magictouch.js all'indirizzo paulirish.com/demo/multi:

Ho testato questo approccio solo con Chrome 10, ma dovrebbe funzionare su altri browser moderni con solo piccole modifiche.

Se il computer non dispone di input multi-touch, puoi simulare gli eventi touch utilizzando altri tracker TUIO, ad esempio reacTIVision. Per ulteriori informazioni, consulta la pagina del progetto TUIO.

Tieni presente che i gesti potrebbero essere identici ai gesti multi-touch a livello di sistema operativo. Su OS X puoi configurare gli eventi a livello di sistema accedendo al riquadro Preferenze del trackpad in Preferenze di Sistema.

Con l'aumento del supporto delle funzionalità multi-touch sui browser mobile, sono entusiasta di vedere che le nuove applicazioni web sfrutteranno appieno questa ricca API.