How to handle event in JavaScript?

Eventos Touch en JavaScript: Guía Completa

hace 10 años

★★★★★Valoración: 4.59 (8652 votos)

En el desarrollo web moderno, la interactividad es clave para ofrecer experiencias de usuario atractivas y dinámicas. JavaScript, el lenguaje de programación esencial para la web, proporciona mecanismos robustos para manejar interacciones del usuario, y entre ellas, los eventos touch ocupan un lugar fundamental, especialmente en el auge de dispositivos móviles y pantallas táctiles.

What is a touch event in JavaScript?
TouchEvent. Represents an event that occurs when the state of touches on the surface changes. Touch. Represents a single point of contact between the user and the touch surface. Jul 26, 2024
Índice de Contenido

¿Qué son los Eventos Touch en JavaScript?

Los eventos touch en JavaScript son aquellos que se disparan cuando un usuario interactúa con una pantalla táctil, ya sea en un smartphone, una tableta o un portátil con pantalla táctil. A diferencia de los eventos de ratón tradicionales (como `click`, `mouseover`, `mouseout`), los eventos touch están diseñados específicamente para reconocer y responder a las acciones realizadas con uno o varios dedos sobre la superficie de la pantalla. Esto incluye acciones como tocar la pantalla, deslizar los dedos, pellizcar para hacer zoom y más.

Estos eventos permiten a los desarrolladores crear interfaces de usuario más intuitivas y naturales para dispositivos táctiles. Imagina una aplicación web que te permite dibujar con el dedo directamente en la pantalla, o una galería de imágenes donde puedes navegar deslizando las fotos con gestos táctiles. Todo esto es posible gracias a la gestión de eventos touch en JavaScript.

Tipos de Eventos Touch Principales

JavaScript define varios tipos de eventos touch para capturar las diferentes etapas de una interacción táctil:

  • touchstart: Este evento se dispara cuando un dedo toca la superficie de la pantalla táctil. Es el punto de inicio de una interacción táctil.
  • touchmove: Se activa repetidamente mientras uno o más dedos se mueven sobre la pantalla. Es esencial para rastrear gestos de arrastre o dibujo.
  • touchend: Ocurre cuando un dedo se levanta de la superficie de la pantalla. Marca el final de un toque.
  • touchcancel: Se dispara cuando se interrumpe un toque de alguna manera. Esto puede suceder si el toque es interrumpido por el sistema (por ejemplo, una alerta del sistema) o si el usuario desliza el dedo fuera del área del navegador.

Manejo de Eventos Touch en la Práctica: Ejemplos con Código

Para empezar a trabajar con eventos touch, primero necesitas adjuntar event listeners a los elementos HTML que deben responder a las interacciones táctiles. Generalmente, esto se hace con el método `addEventListener()`. Consideremos un ejemplo práctico con un elemento `` para dibujar en la pantalla:

function startup() { const el = document.getElementById("canvas"); el.addEventListener("touchstart", handleStart); el.addEventListener("touchend", handleEnd); el.addEventListener("touchcancel", handleCancel); el.addEventListener("touchmove", handleMove); log("Inicializado."); } document.addEventListener("DOMContentLoaded", startup); 

En este código, la función `startup()` se ejecuta una vez que el documento HTML está completamente cargado (`DOMContentLoaded`). Dentro de ella, obtenemos el elemento `` con el ID "canvas" y adjuntamos event listeners para cada tipo de evento touch: `touchstart`, `touchend`, `touchcancel` y `touchmove`. Cada evento está asociado a una función manejadora específica (`handleStart`, `handleEnd`, `handleCancel`, `handleMove`).

Rastreando Nuevos Toques: `touchstart` y `handleStart()`

Cuando ocurre un evento `touchstart`, la función `handleStart()` se encarga de procesarlo. Veamos su implementación:

const ongoingTouches = []; function handleStart(evt) { evt.preventDefault(); log("touchstart."); const el = document.getElementById("canvas"); const ctx = el.getContext("2d"); const touches = evt.changedTouches; for (let i = 0; i < touches.length; i++) { log(`touchstart: ${i}.`); ongoingTouches.push(copyTouch(touches[i])); const color = colorForTouch(touches[i]); log(`color of touch with id ${touches[i].identifier} = ${color}`); ctx.beginPath(); ctx.arc(touches[i].pageX, touches[i].pageY, 4, 0, 2 * Math.PI, false); // un círculo al inicio ctx.fillStyle = color; ctx.fill(); } } 

Aquí, `evt.preventDefault()` previene el comportamiento predeterminado del navegador para eventos touch, lo cual es útil para evitar que se simulen eventos de ratón o que la página se desplace accidentalmente. Obtenemos el contexto 2D del canvas para dibujar. La propiedad `evt.changedTouches` contiene una lista de objetos `Touch` que representan los puntos de contacto que cambiaron su estado en este evento `touchstart` (en este caso, los nuevos toques).

Iteramos sobre cada objeto `Touch` en `touches`. Para cada toque, lo agregamos al array `ongoingTouches` para rastrear los toques activos. Se genera un color aleatorio para cada toque (función `colorForTouch` no mostrada aquí, pero podría asignar un color diferente basado en el ID del toque). Luego, dibujamos un pequeño círculo en las coordenadas del toque (`touches[i].pageX`, `touches[i].pageY`) para indicar el punto de inicio del dibujo.

Dibujando Mientras se Mueven los Dedos: `touchmove` y `handleMove()`

El evento `touchmove` se dispara continuamente mientras los dedos se deslizan por la pantalla. La función `handleMove()` se encarga de dibujar líneas entre la posición anterior y la posición actual de cada toque:

function handleMove(evt) { evt.preventDefault(); const el = document.getElementById("canvas"); const ctx = el.getContext("2d"); const touches = evt.changedTouches; for (let i = 0; i < touches.length; i++) { const color = colorForTouch(touches[i]); const idx = ongoingTouchIndexById(touches[i].identifier); if (idx >= 0) { log(`continuando toque ${idx}`); ctx.beginPath(); log( `ctx.moveTo( ${ongoingTouches[idx].pageX}, ${ongoingTouches[idx].pageY} );`, ); ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY); log(`ctx.lineTo( ${touches[i].pageX}, ${touches[i].pageY} );`); ctx.lineTo(touches[i].pageX, touches[i].pageY); ctx.lineWidth = 4; ctx.strokeStyle = color; ctx.stroke(); ongoingTouches.splice(idx, 1, copyTouch(touches[i])); // Reemplaza el registro del toque anterior } else { log("no se pudo determinar qué toque continuar"); } } } 

Al igual que en `handleStart()`, `evt.preventDefault()` evita el comportamiento predeterminado. Iteramos sobre los toques cambiados (`evt.changedTouches`). La función `ongoingTouchIndexById()` (no mostrada aquí) busca el índice del toque en el array `ongoingTouches` basándose en su `identifier`. El `identifier` es una propiedad única para cada toque que persiste durante la duración del contacto del dedo con la pantalla, permitiéndonos rastrear cada dedo individualmente.

Si encontramos el toque en `ongoingTouches`, significa que ya lo estábamos rastreando. Dibujamos una línea desde la posición anterior del toque (almacenada en `ongoingTouches[idx]`) hasta la posición actual (`touches[i]`). Finalmente, actualizamos la información del toque en `ongoingTouches` con las nuevas coordenadas usando `splice()`, reemplazando el registro anterior con el actual.

Finalizando un Toque: `touchend` y `handleEnd()`

Cuando un usuario levanta un dedo de la pantalla, se dispara el evento `touchend` y se llama a la función `handleEnd()`:

function handleEnd(evt) { evt.preventDefault(); log("touchend"); const el = document.getElementById("canvas"); const ctx = el.getContext("2d"); const touches = evt.changedTouches; for (let i = 0; i < touches.length; i++) { const color = colorForTouch(touches[i]); let idx = ongoingTouchIndexById(touches[i].identifier); if (idx >= 0) { ctx.lineWidth = 4; ctx.fillStyle = color; ctx.beginPath(); ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY); ctx.lineTo(touches[i].pageX, touches[i].pageY); ctx.fillRect(touches[i].pageX - 4, touches[i].pageY - 4, 8, 8); // un cuadrado al final ongoingTouches.splice(idx, 1); // Eliminar el toque del rastreo } else { log("no se pudo determinar qué toque finalizar"); } } } 

Similar a `handleMove()`, dibujamos la última línea del segmento del toque que finaliza. Adicionalmente, dibujamos un pequeño cuadrado al final de la línea para marcar visualmente el punto final del toque. Luego, eliminamos el toque del array `ongoingTouches` usando `splice()`, ya que ya no necesitamos rastrearlo.

Is JavaScript mobile friendly?
JavaScript is used on many desktop and mobile applications because it extends the functionality of web pages, is a relatively easy language to learn and use, and it executes relatively quickly on the client side.

Cancelando Toques: `touchcancel` y `handleCancel()`

El evento `touchcancel` se dispara en situaciones donde el sistema cancela el toque (por ejemplo, si el usuario desliza el dedo hacia la barra de direcciones del navegador). La función `handleCancel()` maneja esta situación:

function handleCancel(evt) { evt.preventDefault(); log("touchcancel."); const touches = evt.changedTouches; for (let i = 0; i < touches.length; i++) { let idx = ongoingTouchIndexById(touches[i].identifier); ongoingTouches.splice(idx, 1); // Eliminar el toque del rastreo } } 

En `handleCancel()`, simplemente eliminamos el toque del array `ongoingTouches` sin dibujar nada, ya que el toque se cancela abruptamente y no queremos completar el dibujo.

Objetos Touch y Propiedades Clave

Cada evento touch (touchstart, touchmove, touchend, touchcancel) proporciona un objeto TouchEvent. Este objeto tiene propiedades importantes, incluyendo:

  • touches: Una lista de todos los objetos `Touch` que están actualmente en contacto con la superficie de la pantalla, independientemente de si cambiaron o no en este evento.
  • targetTouches: Similar a `touches`, pero solo incluye los objetos `Touch` que comenzaron en el mismo elemento DOM que es el objetivo del evento.
  • changedTouches: Una lista de objetos `Touch` cuyo estado ha cambiado en este evento específico. Por ejemplo, en un evento `touchstart`, `changedTouches` contendrá los nuevos toques que acaban de comenzar. En un evento `touchend`, contendrá los toques que acaban de terminar.
  • clientX, clientY: Coordenadas del toque relativas al viewport del cliente (la ventana del navegador).
  • pageX, pageY: Coordenadas del toque relativas al documento HTML completo.
  • screenX, screenY: Coordenadas del toque relativas a la pantalla física.
  • identifier: Un ID único para cada toque individual. Este ID permanece constante para un dedo durante toda la duración del toque, desde `touchstart` hasta `touchend` o `touchcancel`.

Consideraciones Adicionales y Mejores Prácticas

  • Rendimiento: En eventos `touchmove`, que se disparan muy frecuentemente, es crucial optimizar el código dentro de la función manejadora para evitar problemas de rendimiento, especialmente en dispositivos móviles con recursos limitados.
  • Prevención de Comportamiento Predeterminado: Usar `evt.preventDefault()` es importante para controlar completamente la interacción táctil y evitar comportamientos no deseados del navegador, como el desplazamiento o el zoom predeterminados.
  • Multi-Touch: Los eventos touch permiten manejar múltiples toques simultáneamente. Puedes iterar sobre las listas `touches`, `targetTouches` o `changedTouches` para gestionar interacciones con varios dedos (por ejemplo, para implementar gestos de pellizco-zoom).
  • Compatibilidad con Ratón: Si necesitas compatibilidad con dispositivos que no son táctiles, puedes considerar implementar también eventos de ratón (como `mousedown`, `mousemove`, `mouseup`). Algunas bibliotecas y frameworks ayudan a abstraer las diferencias entre eventos touch y mouse para facilitar el desarrollo multiplataforma.

Preguntas Frecuentes (FAQs)

  1. ¿Cuál es la diferencia entre `touches`, `targetTouches` y `changedTouches`?

    `touches` lista todos los toques activos en la pantalla, `targetTouches` solo los que se iniciaron en el elemento objetivo, y `changedTouches` solo los que cambiaron de estado en el evento actual.

  2. ¿Cómo puedo evitar el desplazamiento de la página al usar eventos touch?

    Utiliza `evt.preventDefault()` dentro de tus funciones manejadoras de eventos touch.

  3. ¿Puedo usar eventos touch y eventos de ratón juntos?

    Sí, puedes manejar ambos tipos de eventos para ofrecer compatibilidad tanto con dispositivos táctiles como no táctiles. Sin embargo, ten en cuenta que algunos navegadores pueden simular eventos de ratón después de eventos touch, por lo que puede ser necesario ajustar tu lógica para evitar duplicaciones o comportamientos inesperados.

  4. ¿Qué es el `identifier` en un objeto `Touch`?

    Es un identificador único que se asigna a cada toque individual y se mantiene constante durante la duración del toque. Permite rastrear cada dedo por separado en interacciones multi-touch.

Conclusión

Los eventos touch en JavaScript son una herramienta poderosa para crear experiencias web interactivas y atractivas en dispositivos táctiles. Al comprender los diferentes tipos de eventos touch, cómo manejarlos con event listeners y las propiedades de los objetos `TouchEvent` y `Touch`, puedes desarrollar aplicaciones web que respondan de manera intuitiva a las interacciones táctiles de los usuarios, abriendo un mundo de posibilidades para interfaces de usuario innovadoras y experiencias de usuario enriquecidas en la web moderna.

Subir