Insieme di nuovo per la prima volta
Introduzione
Per quasi trent'anni, le esperienze di utilizzo dei computer desktop si sono concentrate su una tastiera e un mouse o un trackpad come dispositivi di input principali per gli utenti. Negli ultimi dieci anni, però, smartphone e tablet hanno introdotto un nuovo paradigma di interazione: il tocco. Con l'introduzione dei computer Windows 8 con tocco e ora con il rilascio del fantastico Chromebook Pixel con tocco, il tocco sta diventando parte dell'esperienza desktop prevista. Una delle maggiori sfide è creare esperienze che funzionino non solo su dispositivi touch e con mouse, ma anche su questi dispositivi in cui l'utente utilizzerà entrambi i metodi di input, a volte contemporaneamente.
Questo articolo ti aiuterà a capire come le funzionalità touch sono integrate nel browser, come puoi integrare questo nuovo meccanismo di interfaccia nelle tue app esistenti e come il tocco può interagire con l'input del mouse.
Lo stato del tocco nella piattaforma web
L'iPhone è stata la prima piattaforma popolare ad avere API touch dedicate integrate nel browser web. Diversi altri fornitori di browser hanno creato interfacce API simili progettate per essere compatibili con l'implementazione di iOS, ora descritta dalla specifica "Touch Events versione 1". Gli eventi tocco sono supportati da Chrome e Firefox su computer, da Safari su iOS, da Chrome e dal browser Android su Android, nonché da altri browser mobile come il browser BlackBerry.
Il mio collega Boris Smus ha scritto un ottimo tutorial di HTML5Rocks sugli eventi tocco che è ancora un buon modo per iniziare se non hai mai esaminato gli eventi tocco. Infatti, se non hai mai lavorato con gli eventi tocco, leggi l'articolo prima di continuare. Vai, ti aspetto.
Hai finito? Ora che hai una conoscenza di base degli eventi tocco, la difficoltà di scrivere interazioni supportate dal tocco è che queste possono essere molto diverse dagli eventi del mouse (e del trackpad e della trackball che simulano il mouse). Sebbene le interfacce touch in genere cerchino di emulare i mouse, questa emulazione non è perfetta o completa. Devi quindi utilizzare entrambi gli stili di interazione e potresti dover supportare ogni interfaccia in modo indipendente.
L'aspetto più importante: l'utente potrebbe avere un tocco e un mouse
Molti sviluppatori hanno creato siti che rilevano in modo statico se un ambiente supporta gli eventi tocco e poi presumono di dover supportare solo gli eventi tocco (e non del mouse). Questa è un'ipotesi errata: il fatto che siano presenti eventi touch non significa che l'utente utilizzi principalmente il dispositivo di input touch. Dispositivi come Chromebook Pixel e alcuni laptop Windows 8 ora supportano ENTRAMBI i metodi di input del mouse e del tocco e altri lo faranno nel prossimo futuro. Su questi dispositivi, è abbastanza naturale per gli utenti utilizzare sia il mouse sia il touchscreen per interagire con le applicazioni, quindi "supporta il tocco" non è sinonimo di "non richiede il supporto del mouse". Non puoi pensare al problema come "devo scrivere due stili di interazione diversi e passare da uno all'altro", devi pensare a come entrambe le interazioni funzioneranno insieme e in modo indipendente. Sul mio Chromebook Pixel uso spesso il trackpad, ma allungo anche la mano e tocco lo schermo. Nella stessa applicazione o pagina, faccio ciò che mi sembra più naturale in quel momento. D'altra parte, alcuni utenti di laptop con touchscreen non lo useranno mai o quasi mai, quindi la presenza di input tocco non dovrebbe disattivare o ostacolare il controllo del mouse.
Purtroppo, può essere difficile sapere se l'ambiente del browser di un utente supporta o meno l'input tocco. Idealmente, un browser su un computer desktop dovrebbe sempre indicare il supporto per gli eventi tocco, in modo che un display touchscreen possa essere collegato in qualsiasi momento (ad esempio se diventa disponibile un touchscreen collegato tramite un KVM). Per tutti questi motivi, le tue applicazioni non devono tentare di passare dal tocco al mouse, ma supportare entrambi.
Supporto congiunto di mouse e tocco
1. Clic e tocco: l'ordine "naturale" delle cose
Il primo problema è che le interfacce touch in genere cercano di emulare i clic del mouse, ovviamente perché devono funzionare su applicazioni che in precedenza hanno interagito solo con gli eventi del mouse. Puoi utilizzarla come scorciatoia, perché gli eventi "click" continueranno a essere attivati, indipendentemente dal fatto che l'utente abbia fatto clic con il mouse o abbia toccato lo schermo con un dito. Tuttavia, ci sono un paio di problemi con questa scorciatoia.
Innanzitutto, devi fare attenzione quando progetti interazioni touch più avanzate: quando l'utente utilizza un mouse, il sistema risponde tramite un evento di clic, ma quando l'utente tocca lo schermo si verificano sia eventi di tocco che di clic. Per un singolo clic, l'ordine degli eventi è:
- touchstart
- touchmove
- touchend
- mouseover
- mousemove
- mousedown
- mouseup
- clic
Ciò significa, ovviamente, che se stai elaborando eventi touch come touchstart, devi assicurarti di non elaborare anche l'evento mousedown e/o click corrispondente. Se puoi annullare gli eventi tocco (chiamare preventDefault() all'interno del gestore eventi), non verranno generati eventi del mouse per il tocco. Una delle regole più importanti degli handler tocco è:
Tuttavia, questo impedisce anche altri comportamenti predefiniti del browser (come lo scorrimento), anche se in genere gestisci l'evento tocco interamente nel gestore e vuoi disattivare le azioni predefinite. In genere, è consigliabile gestire e annullare tutti gli eventi tocco oppure evitare di avere un gestore per questo evento.
In secondo luogo, quando un utente tocca un elemento in una pagina web su un dispositivo mobile, le pagine che non sono state progettate per l'interazione mobile hanno un ritardo di almeno 300 millisecondi tra l'evento touchstart e l'elaborazione degli eventi del mouse (mousedown). Puoi farlo utilizzando Chrome. Puoi attivare l'opzione "Emulare eventi tocco" negli Strumenti per sviluppatori di Chrome per testare le interfacce touch su un sistema non touch.
Questo ritardo consente al browser di determinare se l'utente sta eseguendo un altro gesto, in particolare lo zoom con doppio tocco. Ovviamente, questo può essere problematico nei casi in cui vuoi avere una risposta istantanea al tocco di un dito. Sono in corso dei lavori per cercare di limitare gli scenari in cui si verifica automaticamente questo ritardo.
Il primo e più semplice modo per evitare questo ritardo è "dire" al browser mobile che la tua pagina non richiede lo zoom, il che può essere fatto utilizzando un'area visibile fissa, ad esempio inserendo nella pagina:
<meta name="viewport" content="width=device-width,user-scalable=no">
Naturalmente, questa opzione non è sempre appropriata, perché disattiva lo zoom con due dita, che potrebbe essere necessario per motivi di accessibilità, quindi utilizzala con parsimonia, se non del tutto (se disattivi la scalabilità dell'utente, ti consigliamo di fornire un altro modo per aumentare la leggibilità del testo nella tua applicazione). Inoltre, questo ritardo non si applica a Chrome sui dispositivi di classe desktop che supportano il tocco e ad altri browser su piattaforme mobile quando la pagina ha viewport non scalabili.
#2: gli eventi Mousemove non vengono attivati dal tocco
A questo punto è importante notare che l'emulazione degli eventi del mouse in un'interfaccia touch in genere non si estende all'emulazione degli eventi mousemove. Pertanto, se crei un bel controllo basato sul mouse che utilizza gli eventi mousemove, probabilmente non funzionerà con un dispositivo touch, a meno che non aggiungi anche gestori touchmove specifici.
In genere, i browser implementano automaticamente l'interazione appropriata per le interazioni touch sui controlli HTML. Ad esempio, i controlli di intervallo HTML5 funzioneranno solo quando utilizzi le interazioni touch. Tuttavia, se hai implementato i tuoi controlli, probabilmente non funzioneranno con le interazioni di tipo clic e trascinamento. Infatti, alcune librerie di uso comune (come jQueryUI) non supportano ancora in modo nativo le interazioni touch in questo modo (anche se per jQueryUI esistono diversi fix di monkey-patch per questo problema). Questo è stato uno dei primi problemi che ho riscontrato durante l'upgrade dell'applicazione Web Audio Playground per il funzionamento con il tocco: i cursori erano basati su jQueryUI, quindi non funzionavano con le interazioni di trascinamento. Ho passato ai controlli intervallo HTML5 e funzionano. In alternativa, avrei potuto semplicemente aggiungere gestori touchmove per aggiornare i cursori, ma c'è un problema…
#3: Touchmove e MouseMove non sono la stessa cosa
Un errore che ho visto commettere da alcuni sviluppatori è quello di chiamare gli handler touchmove e mousemove negli stessi percorsi di codice. Il comportamento di questi eventi è molto simile, ma leggermente diverso: in particolare, gli eventi tocco hanno sempre come target l'elemento in cui è iniziato il tocco, mentre gli eventi del mouse hanno come target l'elemento attualmente sotto il cursore del mouse. Questo è il motivo per cui abbiamo gli eventi mouseover e mouseout, ma non sono presenti eventi touchover e touchout corrispondenti, solo touchend.
Il modo più comune in cui questo può accadere è se rimuovi (o sposti) l'elemento che l'utente ha iniziato a toccare. Ad esempio, immagina un carosello di immagini con un gestore tocco sull'intero carosello per supportare il comportamento di scorrimento personalizzato. Man mano che le immagini disponibili cambiano, rimuovi alcuni elementi <img>
e ne aggiungi altri. Se l'utente inizia a toccare una di queste immagini e poi la rimuovi, il gestore (che si trova in un antenato dell'elemento img) smetterà di ricevere eventi tocco (poiché vengono inviati a un target che non è più nell'albero). Sembrerà che l'utente tenga il dito in un punto anche se potrebbe averlo spostato e alla fine averlo rimosso.
Ovviamente, puoi evitare questo problema evitando di rimuovere elementi che hanno (o hanno antenati che hanno) gestori di tocco mentre è attivo un tocco. In alternativa, la soluzione migliore è non registrare gestori statici di touchend/touchmove, ma attendere di ricevere un evento touchstart e poi aggiungere gestori di touchmove/touchend/touchcancel al target dell'evento touchstart (e rimuoverli su end/cancel). In questo modo continuerai a ricevere eventi per il tocco anche se l'elemento di destinazione viene spostato/rimosso. Puoi fare qualche prova qui: tocca la casella rossa e tieni premuto Esc per rimuoverla dal DOM.
#4: tocco ed effetto hover
La metafora del cursore del mouse separava la posizione del cursore dalla selezione attiva e consentiva agli sviluppatori di utilizzare gli stati di passaggio del mouse per nascondere e mostrare informazioni che potrebbero essere pertinenti per gli utenti. Tuttavia, la maggior parte delle interfacce touch al momento non rileva un dito "sopra" un target, quindi fornire informazioni semanticamente importanti (ad es. un popup "Che cos'è questo controllo?") in base al passaggio del mouse è un tabù, a meno che non fornisca anche un modo compatibile con il tocco per accedere a queste informazioni. Devi fare attenzione a come utilizzi il passaggio del mouse per trasmettere informazioni agli utenti.
È interessante notare, però, che in alcuni casi la pseudoclasse CSS :hover PUÒ essere attivata dalle interfacce touch: toccare un elemento lo rende :active mentre il dito è premuto e acquisisce anche lo stato :hover. In Internet Explorer, :hover è attivo solo mentre il dito dell'utente è premuto; in altri browser, :hover rimane attivo fino al successivo tocco o movimento del mouse. Questo è un buon approccio per far funzionare i menu popup sulle interfacce touch. Un effetto collaterale dell'attivazione di un elemento è che viene applicato anche lo stato :hover. Ad esempio:
<style>
img ~ .content {
display:none;
}
img:hover ~ .content {
display:block;
}
</style>
<img src="/awesome.png">
<div class="content">This is an awesome picture of me</div>
Una volta toccato un altro elemento, questo non è più attivo e lo stato di passaggio del mouse scompare, proprio come se l'utente avesse utilizzato il cursore del mouse e lo avesse spostato dall'elemento. Ti consigliamo di racchiudere i contenuti in un elemento <a>
per renderli anche un punto di tabulazione. In questo modo, l'utente può attivare/disattivare le informazioni aggiuntive passando il mouse sopra o facendo clic, toccando o premendo un tasto, senza che sia necessario JavaScript. Quando ho iniziato a lavorare per far funzionare bene Web Audio Playground con le interfacce touch, ho scoperto con piacere che i miei menu popup funzionavano già bene con il tocco, perché avevo utilizzato questo tipo di struttura.
Il metodo riportato sopra funziona bene per le interfacce basate sul cursore del mouse e per le interfacce touch. Ciò è in contrasto con l'utilizzo degli attributi "title" al passaggio del mouse, che NON vengono visualizzati quando l'elemento è attivato:
<img src="/awesome.png" title="this doesn't show up in touch">
5. Precisione del tocco rispetto al mouse
Sebbene i mouse non siano perfettamente in linea con la realtà, sono estremamente precisi, in quanto il sistema operativo sottostante monitora generalmente la precisione esatta dei pixel per il cursore. Gli sviluppatori di app mobile, invece, hanno imparato che i tocchi con le dita su un touch screen non sono altrettanto precisi, soprattutto a causa delle dimensioni della superficie del dito quando è a contatto con lo schermo (e in parte perché le dita ostruiscono lo schermo).
Molte persone e aziende hanno condotto ricerche approfondite sugli utenti per capire come progettare applicazioni e siti che supportano l'interazione con le dita e sono stati scritti molti libri sull'argomento. Il consiglio di base è aumentare le dimensioni dei target di tocco aumentando i margini e ridurre la probabilità di tocchi errati aumentando il margine tra gli elementi. I margini non sono inclusi nella gestione del rilevamento dei hit degli eventi di tocco e clic, mentre lo è il padding. Una delle correzioni principali che ho dovuto apportare a Web Audio Playground è stata aumentare le dimensioni dei punti di connessione in modo che fossero più facilmente toccabili con precisione.
Molti fornitori di browser che gestiscono interfacce basate sul tocco hanno anche introdotto nel browser una logica per aiutare a scegliere come target l'elemento corretto quando un utente tocca lo schermo e ridurre la probabilità di clic errati, anche se in genere vengono corretti solo gli eventi di clic, non i movimenti (anche se sembra che Internet Explorer modifichi anche gli eventi mousedown/mousemove/mouseup).
#6: mantieni contenuti i gestori tocco, altrimenti la visualizzazione scorrerà in modo discontinuo
È inoltre importante limitare i gestori tocco solo agli elementi in cui sono necessari. Poiché gli elementi tocco possono richiedere una larghezza di banda molto elevata, è importante evitare i gestori tocco negli elementi in cui si scorre (poiché l'elaborazione potrebbe interferire con le ottimizzazioni del browser per lo scorrimento tocco veloce e senza scatti. I browser moderni tentano di scorrere su un thread GPU, ma ciò è impossibile se devono prima controllare con JavaScript se ogni evento tocco verrà gestito dall'app). Puoi consultare un esempio di questo comportamento.
Una linea guida da seguire per evitare questo problema è assicurarti che, se gestisci gli eventi tocco solo in una piccola parte dell'interfaccia utente, colleghi i gestori tocco solo lì (ad es. non nel <body>
della pagina); in breve, limita il più possibile l'ambito dei gestori tocco.
#7: Multi-touch
L'ultima sfida interessante è che, anche se la chiamiamo interfaccia utente "Touch", quasi universalmente il supporto è in realtà per il multi-touch, ovvero le API forniscono più di un input tocco alla volta. Quando inizi a supportare il tocco nelle tue applicazioni, devi considerare in che modo più tocchi potrebbero influire sulla tua applicazione.
Se hai creato app principalmente con il mouse, probabilmente sei abituato a creare app con al massimo un punto del cursore, in quanto i sistemi in genere non supportano più cursori del mouse. Per molte applicazioni, dovrai solo mappare gli eventi tocco a un'unica interfaccia del cursore, ma la maggior parte dell'hardware che abbiamo visto per l'input tocco da computer può gestire almeno 2 input simultanei e la maggior parte del nuovo hardware sembra supportare almeno 5 input simultanei. Per sviluppare una tastiera di pianoforte sullo schermo, ovviamente, devi essere in grado di supportare più input tocco simultanei.
Le API W3C Touch attualmente implementate non hanno un'API per determinare il numero di punti di contatto supportati dall'hardware, quindi dovrai utilizzare la tua migliore stima del numero di punti di contatto che i tuoi utenti vorranno oppure, ovviamente, prestare attenzione al numero di punti di contatto che vedi in pratica e adattarti. Ad esempio, in un'applicazione per pianoforte, se non vedi mai più di due punti di contatto, ti consigliamo di aggiungere un'interfaccia utente "accordi". L'API PointerEvents ha un'API per determinare le funzionalità del dispositivo.
Ritocco
Ci auguriamo che questo articolo ti abbia fornito alcune indicazioni sulle sfide comuni nell'implementazione del tocco insieme alle interazioni con il mouse. Più importante di qualsiasi altro consiglio, ovviamente, è che devi testare la tua app su dispositivi mobili, tablet ed ambienti desktop combinati con mouse e tocco. Se non hai hardware touch e mouse, utilizza l'opzione "Emulare eventi tocco" di Chrome per testare i diversi scenari.
Seguendo queste indicazioni, non solo è possibile, ma è anche relativamente facile creare esperienze interattive coinvolgenti che funzionino bene con input tocco, input del mouse e persino con entrambi gli stili di interazione contemporaneamente.