Modo táctil y mouse

Vuelven a estar juntos por primera vez

Introducción

Durante casi treinta años, las experiencias de computación de escritorio se centraron en un teclado y un mouse o panel táctil como nuestros principales dispositivos de entrada de usuario. Sin embargo, en la última década, los smartphones y las tablets introdujeron un nuevo paradigma de interacción: el tacto. Con la introducción de máquinas con Windows 8 compatibles con la función táctil y, ahora, con el lanzamiento de la increíble Chromebook Pixel con esta función, la tecnología táctil se está convirtiendo en parte de la experiencia esperada en computadoras de escritorio. Uno de los mayores desafíos es crear experiencias que funcionen no solo en dispositivos táctiles y con mouse, sino también en estos dispositivos en los que el usuario usará ambos métodos de entrada, a veces de forma simultánea.

Este artículo te ayudará a comprender cómo están integradas las capacidades táctiles en el navegador, cómo puedes integrar este nuevo mecanismo de interfaz en tus apps existentes y cómo el tacto puede funcionar bien con la entrada del mouse.

El estado de la función táctil en la plataforma web

El iPhone fue la primera plataforma popular en tener APIs táctiles dedicadas integradas en el navegador web. Varios proveedores de navegadores crearon interfaces de API similares compiladas para ser compatibles con la implementación de iOS, que ahora se describe en la especificación "Eventos táctiles versión 1". Los eventos táctiles son compatibles con Chrome y Firefox en computadoras, Safari en iOS, Chrome y el navegador de Android en Android, así como con otros navegadores para dispositivos móviles, como el navegador de Blackberry.

Mi colega Boris Smus escribió un excelente instructivo de HTML5Rocks sobre eventos táctiles, que sigue siendo una buena forma de comenzar si nunca antes viste los eventos táctiles. De hecho, si nunca antes trabajaste con eventos táctiles, lee ese artículo ahora, antes de continuar. Adelante, esperaré.

¿Terminaste? Ahora que tienes una base básica en los eventos táctiles, el desafío de escribir interacciones táctiles es que las interacciones táctiles pueden ser bastante diferentes de los eventos del mouse (y del panel táctil que emula el mouse y la bola de seguimiento). Si bien las interfaces táctiles suelen intentar emular mouse, esa emulación no es perfecta ni completa. Necesitas trabajar a través de ambos estilos de interacción y es posible que debas admitir cada interfaz de forma independiente.

Lo más importante: Es posible que el usuario tenga un mouse y la función de tacto

Muchos desarrolladores crearon sitios que detectan de forma estática si un entorno admite eventos táctiles y, luego, suponen que solo deben admitir eventos táctiles (y no del mouse). Esta ahora es una suposición errónea; en cambio, el hecho de que haya eventos táctiles no significa que el usuario esté usando principalmente ese dispositivo de entrada táctil. Dispositivos como la Chromebook Pixel y algunas laptops con Windows 8 ahora admiten los métodos de entrada táctil y del mouse, y pronto se agregarán más. En estos dispositivos, es bastante natural que los usuarios usen el mouse y la pantalla táctil para interactuar con las aplicaciones, por lo que "admite la función táctil" no es lo mismo que "no necesita compatibilidad con el mouse". No puedes pensar en el problema como "Tengo que escribir dos estilos de interacción diferentes y alternar entre ellos". Debes pensar en cómo ambas interacciones funcionarán juntas y de forma independiente. En mi Chromebook Pixel, suelo usar el panel táctil con frecuencia, pero también levanto la pantalla y toco la pantalla. En la misma aplicación o página, hago lo que sea más natural en ese momento. Por otro lado, algunos usuarios de laptops con pantalla táctil rara vez, o nunca, usan la pantalla táctil, por lo que la presencia de la entrada táctil no debe inhabilitar ni obstaculizar el control del mouse.

Lamentablemente, puede ser difícil saber si el entorno del navegador de un usuario admite o no la entrada táctil. Idealmente, un navegador en una máquina de escritorio siempre indicaría la compatibilidad con eventos táctiles para que se pueda conectar una pantalla táctil en cualquier momento (p. ej., si una pantalla táctil conectada a través de un KVM está disponible). Por todos estos motivos, tus aplicaciones no deben intentar alternar entre la entrada táctil y el mouse, sino que deben admitir ambas.

Compatibilidad con mouse y Touch Together

#1: Hacer clic y presionar: el orden "natural" de las cosas

El primer problema es que las interfaces táctiles suelen intentar emular los clics del mouse, por lo que deben funcionar en aplicaciones que solo interactuaron con eventos del mouse. Puedes usar esto como una combinación de teclas, ya que los eventos de "clic" se seguirán activando, ya sea que el usuario haga clic con el mouse o toque la pantalla con el dedo. Sin embargo, hay algunos problemas con este atajo.

Primero, debes tener cuidado cuando diseñes interacciones táctiles más avanzadas: cuando el usuario use un mouse, responderá a través de un evento de clic, pero cuando el usuario toque la pantalla, se producirán eventos táctiles y de clic. Para un solo clic, el orden de los eventos es el siguiente:

  1. touchstart
  2. touchmove
  3. touchend
  4. desplazar el mouse sobre un anuncios
  5. mousemove
  6. mousedown
  7. mouseup
  8. click

Esto, por supuesto, significa que, si procesas eventos táctiles como touchstart, debes asegurarte de no procesar el evento mousedown o click correspondiente. Si puedes cancelar los eventos táctiles (llama a preventDefault() dentro del controlador de eventos), no se generarán eventos del mouse para la acción táctil. Una de las reglas más importantes de los controladores táctiles es la siguiente:

Sin embargo, esto también evita otros comportamientos predeterminados del navegador (como el desplazamiento), aunque, por lo general, controlas el evento táctil por completo en tu controlador y querrás inhabilitar las acciones predeterminadas. En general, te recomendamos que controles y canceles todos los eventos táctiles, o bien que evites tener un controlador para ese evento.

En segundo lugar, cuando un usuario presiona un elemento en una página web en un dispositivo móvil, las páginas que no se diseñaron para la interacción con dispositivos móviles tienen una demora de al menos 300 milisegundos entre el evento touchstart y el procesamiento de los eventos del mouse (mousedown). Se puede hacer con Chrome. Puedes activar la opción "Emular eventos táctiles" en las herramientas para desarrolladores de Chrome para probar interfaces táctiles en un sistema no táctil.

Esta demora permite que el navegador determine si el usuario está realizando otro gesto, en particular, el zoom con dos toques. Obviamente, esto puede ser problemático en los casos en los que deseas tener una respuesta instantánea al toque de un dedo. Se está trabajando para intentar limitar las situaciones en las que se produce esta demora automáticamente.

Chrome para Android Navegador Android Opera Mobile para Android). Firefox para Android Safari para iOS
Viewport no escalable Sin retraso 300 ms 300 ms Sin retraso 300 ms
Sin viewport 300 ms 300 ms 300 ms 300 ms 300 ms

La primera y más fácil manera de evitar esta demora es "decirle" al navegador para dispositivos móviles que tu página no necesitará zoom, lo que se puede hacer con un viewport fijo, por ejemplo, insertando lo siguiente en tu página:

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

Por supuesto, esto no siempre es adecuado, ya que inhabilita el zoom con pellizco, que puede ser necesario por motivos de accesibilidad, por lo que debes usarlo con moderación (si inhabilitas la escala del usuario, te recomendamos que proporciones otra forma de aumentar la legibilidad del texto en tu aplicación). Además, en el caso de Chrome en dispositivos de clase de computadoras de escritorio que admiten la función táctil y otros navegadores en plataformas para dispositivos móviles cuando la página tiene viewports que no son escalables, no se aplica esta demora.

#2: Los eventos de movimiento del mouse no se activan con el toque

En este punto, es importante tener en cuenta que la emulación de eventos del mouse en una interfaz táctil no suele extenderse a la emulación de eventos de movimiento del mouse. Por lo tanto, si compilas un control atractivo controlado por el mouse que usa eventos de movimiento del mouse, es probable que no funcione con un dispositivo táctil, a menos que también agregues controladores de movimiento táctil de forma específica.

Por lo general, los navegadores implementan automáticamente la interacción adecuada para las interacciones táctiles en los controles HTML, por lo que, por ejemplo, los controles de rango HTML5 solo funcionarán cuando uses interacciones táctiles. Sin embargo, si implementaste tus propios controles, es probable que no funcionen en interacciones de tipo hacer clic y arrastrar. De hecho, algunas bibliotecas de uso general (como jQueryUI) aún no admiten de forma nativa interacciones táctiles de esta manera (aunque para jQueryUI, hay varias correcciones de parches para este problema). Este fue uno de los primeros problemas que encontré cuando actualicé mi aplicación de Web Audio Playground para que funcionara con la función táctil. Los controles deslizantes se basaban en jQueryUI, por lo que no funcionaban con interacciones de arrastrar y soltar. Cambié a los controles de rango HTML5 y funcionaron. Alternativamente, por supuesto, podría haber agregado simplemente controladores touchmove para actualizar los controles deslizantes, pero hay un problema con eso...

#3: Touchmove y MouseMove no son lo mismo

Un error que he visto cometer a algunos desarrolladores es hacer que los controladores de touchmove y mousemove llamen a las mismas instrucciones de código. El comportamiento de estos eventos es muy similar, pero sutilmente diferente. En particular, los eventos táctiles siempre se orientan al elemento en el que SE INICIÓ ese toque, mientras que los eventos del mouse se orientan al elemento que se encuentra debajo del cursor del mouse. Por este motivo, tenemos eventos de desplazamiento del mouse sobre y fuera del elemento, pero no hay eventos de desplazamiento del mouse sobre y fuera del elemento táctil, solo touchend.

La forma más común en que esto puede afectarte es si quitas (o reubicas) el elemento que el usuario comenzó a tocar. Por ejemplo, imagina un carrusel de imágenes con un controlador de tacto en todo el carrusel para admitir un comportamiento de desplazamiento personalizado. A medida que cambian las imágenes disponibles, quitas algunos elementos <img> y agregas otros. Si el usuario comienza a tocar una de esas imágenes y, luego, la quitas, tu controlador (que se encuentra en un ancestro del elemento img) simplemente dejará de recibir eventos táctiles (porque se envían a un destino que ya no está en el árbol). Parecerá que el usuario mantiene el dedo en un lugar, aunque es posible que lo haya movido y, finalmente, lo haya quitado.

Por supuesto, puedes evitar este problema si no quitas elementos que tengan controladores de tacto (o que tengan elementos superiores que tengan controladores de tacto) mientras un toque está activo. Como alternativa, la mejor guía es, en lugar de registrar controladores estáticos de touchend/touchmove, esperar hasta que se obtenga un evento touchstart y, luego, agregar controladores de touchmove/touchend/touchcancel al objetivo del evento touchstart (y quitarlos al final o cancelarlos). De esta manera, seguirás recibiendo eventos para el toque, incluso si se mueve o quita el elemento de destino. Aquí puedes jugar con esto: toca el cuadro rojo y mantén presionado Escape para quitarlo del DOM.

#4: Tocar y colocar el cursor sobre

La metáfora del puntero del mouse separó la posición del cursor de la selección activa, lo que permitió a los desarrolladores usar estados de desplazamiento del mouse para ocultar y mostrar información que podría ser pertinente para los usuarios. Sin embargo, la mayoría de las interfaces táctiles en la actualidad no detectan un dedo que se coloca sobre un objetivo, por lo que proporcionar información semánticamente importante (p.ej., una ventana emergente que diga "¿Qué es este control?") basada en el desplazamiento del mouse es un error, a menos que también proporciones una forma táctil de acceder a esta información. Debes tener cuidado cuando usas el desplazamiento del cursor para transmitir información a los usuarios.

Sin embargo, es interesante que, en algunos casos, las interfaces táctiles PUEDEN activar la pseudoclase :hover de CSS. Si presionas un elemento, se vuelve :active mientras el dedo está presionado y también adquiere el estado :hover. (Con Internet Explorer, el :hover solo tiene efecto mientras el dedo del usuario está presionado; otros navegadores mantienen el :hover en efecto hasta el siguiente toque o movimiento del mouse). Este es un buen enfoque para hacer que los menús emergentes funcionen en interfaces táctiles. Un efecto secundario de hacer que un elemento sea activo es que también se aplica el estado :hover. Por ejemplo:

<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 vez que se presiona otro elemento, este ya no está activo y desaparece el estado de desplazamiento del mouse, tal como si el usuario estuviera usando un puntero del mouse y lo hubiera quitado del elemento. Es posible que quieras unir el contenido a un elemento <a> para convertirlo en una tabulación. De esta manera, el usuario puede activar o desactivar la información adicional con el desplazamiento del mouse o un clic, un toque táctil o una tecla, sin necesidad de JavaScript. Me sorprendió gratamente cuando comencé a trabajar para que mi Web Audio Playground funcionara bien con interfaces táctiles que mis menús emergentes ya funcionaban bien con el tacto, porque usé este tipo de estructura.

El método anterior funciona bien para interfaces basadas en el puntero del mouse y también para interfaces táctiles. Esto contrasta con el uso de atributos "title" cuando se coloca el cursor sobre un elemento, que NO aparecerá cuando se active el elemento:

<img src="/awesome.png" title="this doesn't show up in touch">

#5: Precisión del toque en comparación con la del mouse

Si bien los mouses tienen una disociación conceptual de la realidad, resulta que son extremadamente precisos, ya que el sistema operativo subyacente generalmente realiza un seguimiento de la precisión exacta del píxel para el cursor. Por otro lado, los desarrolladores de dispositivos móviles descubrieron que los toques de los dedos en una pantalla táctil no son tan precisos, principalmente debido al tamaño del área de la superficie del dedo cuando está en contacto con la pantalla (y en parte porque los dedos obstruyen la pantalla).

Muchas personas y empresas realizaron una investigación exhaustiva sobre los usuarios para diseñar aplicaciones y sitios que se adapten a la interacción con los dedos, y se escribieron muchos libros sobre el tema. El consejo básico es aumentar el tamaño de los objetivos táctiles aumentando el padding y reducir la probabilidad de toques incorrectos aumentando el margen entre los elementos. (Los márgenes no se incluyen en el control de detección de hits de los eventos de toque y clic, mientras que el padding sí). Una de las correcciones principales que tuve que hacer en Web Audio Playground fue aumentar el tamaño de los puntos de conexión para que se pudieran tocar con mayor precisión.

Muchos proveedores de navegadores que controlan interfaces táctiles también introdujeron lógica en el navegador para ayudar a segmentar el elemento correcto cuando un usuario toca la pantalla y reducir la probabilidad de clics incorrectos, aunque esto suele corregir solo los eventos de clic, no los movimientos (aunque Internet Explorer también parece modificar los eventos de mousedown/mousemove/mouseup).

#6: Mantén contenidos los controladores de tacto, o bien se interrumpirá el desplazamiento

También es importante que los controladores táctiles se limiten solo a los elementos donde los necesites. Los elementos táctiles pueden requerir un ancho de banda muy alto, por lo que es importante evitar los controladores táctiles en los elementos que se desplazan (ya que el procesamiento puede interferir con las optimizaciones del navegador para un desplazamiento rápido sin bloqueos). Los navegadores modernos intentan desplazarse en un subproceso de la GPU, pero esto es imposible si tienen que verificar primero con JavaScript para ver si cada evento táctil será controlado por la app. Puedes consultar un ejemplo de este comportamiento.

Una guía que debes seguir para evitar este problema es asegurarte de que, si solo controlas eventos táctiles en una pequeña parte de tu IU, solo adjuntes controladores táctiles allí (no, p. ej., en el <body> de la página). En resumen, limita el alcance de tus controladores táctiles tanto como sea posible.

#7: Pantalla multitáctil

El último desafío interesante es que, aunque nos referimos a ella como interfaz de usuario "táctil", la compatibilidad es casi universal para la tecnología multitáctil, es decir, las APIs proporcionan más de una entrada táctil a la vez. A medida que comiences a admitir las funciones táctiles en tus aplicaciones, debes considerar cómo podrían afectarla múltiples toques.

Si compilaste apps principalmente con el mouse, estás acostumbrado a compilar con un máximo de un punto de cursor. Por lo general, los sistemas no admiten varios cursores de mouse. En muchas aplicaciones, solo asignarás eventos táctiles a una sola interfaz de cursor, pero la mayoría del hardware que vimos para la entrada táctil de computadoras de escritorio puede controlar al menos 2 entradas simultáneas, y la mayoría del hardware nuevo parece admitir al menos 5 entradas simultáneas. Por supuesto, para desarrollar un teclado de piano en pantalla, querrás poder admitir varias entradas táctiles simultáneas.

Las APIs de W3C Touch implementadas actualmente no tienen una API para determinar cuántos puntos de contacto admite el hardware, por lo que deberás usar tu mejor estimación de cuántos puntos de contacto querrán tus usuarios o, por supuesto, prestar atención a cuántos puntos de contacto ves en la práctica y adaptarte. Por ejemplo, en una aplicación de piano, si nunca ves más de dos puntos de contacto, puedes agregar algunas IU de "acordes". La API de PointerEvents tiene una API para determinar las capacidades del dispositivo.

Retoques

Esperamos que este artículo te haya brindado orientación sobre los desafíos comunes que se presentan a la hora de implementar la función táctil junto con las interacciones del mouse. Por supuesto, lo más importante que debes hacer es probar tu app en dispositivos móviles, tablets y entornos combinados de mouse y pantalla táctil para computadoras de escritorio. Si no tienes hardware táctil ni mouse, usa la opción "Emular eventos táctiles" de Chrome para probar las diferentes situaciones.

No solo es posible, sino que es relativamente fácil seguir estas instrucciones para crear experiencias interactivas atractivas que funcionen bien con la entrada táctil, la entrada del mouse y hasta ambos estilos de interacción al mismo tiempo.