CSSLab: iPad

iPad, iPad, iPad… otro nuevo dispositivo para cautivar a los ávidos consumidores, pero que por lo menos trae interesantes nuevas tecnologías. Aparte de que crean que es un iPhone gigante, tiene varias innovaciones que permiten darle mucha rienda a la imaginación de los creadores de contenido específico para esta plataforma. Una de las que más me han interesados, corresponde a los eventos gestuales.

Este artículo abordará todos los eventos disponibles para iPad y que ocurren cuando el usuario interactúa con una página web en iOS. Aunque puedes visualizar los ejemplos con Safari 5 para escritorio o el mismo iPhone, la mejor interacción la puedes lograr desde un iPad mismo por la dimensión y calidad de su superficie táctil (o en su defecto con su simulador).

Eventos Multitouch

CSSLab - Eventos Multitouch

Puedes usar classes de eventos touch de tipo DOM en Javascript que ya están disponibles en iOS. Si quieres registrar estos eventos, el sistema envía objetos TouchEvent a aquellos elementos DOM mientras los dedos se mueven por sobre la superficie. Una secuencia multitouch comienza cuando un dedo toca por primera vez la superficie. La secuencia termina cuando el último de esos dedos se levanta de la misma superficie. Éstos eventos son similares a los usuales eventos de mouse, excepto que puedes tener toques simultáneos en la superficie en diferentes lugares de la misma. Un objeto de evento touch es utilizado para encapsular todos los toques que existen en un mismo momento en la pantalla. Cada dedo es representado por un objeto touch y las típicas propiedades que encuentras en un evento de mouse están en un evento touch, pero no el objeto mismo.

Cuatro son los principales eventos touch:

ontouchstart
<dd>
  ocurre cada vez que un dedo se posa sobre la pantalla.
</dd>

<dt>
  ontouchmove
</dt>

<dd>
  ocurre cuando un dedo que ya est&aacute; en la pantalla se mueve sobre ella.
</dd>

<dt>
  ontouchend
</dt>

<dd>
  ocurre cada vez que un dedo sale de la pantalla.
</dd>

<dt>
  ontouchcancel
</dt>

<dd>
  el sistema puede cancelar los eventos en ciertas ocasiones, como por ej. cuando recibes un <strong>SMS</strong> mientras est&aacute;s arrastrando un elemento.
</dd>

Para registrarlos con Javascript:

element.addEventListener("touchstart", touchStart, false);
element.addEventListener("touchmove", touchMove, false);
element.addEventListener("touchend", touchEnd, false);
element.addEventListener("touchcancel", touchCancel, false);

Y si lo quieres implementar como una función:

function touchStart(event) {
   <span class="commentjs">// tomemos las coordenadas del dedo cuando toca la pantalla</span>
   var x = event.touches[0].pageX;
   var y = event.touches[0].pageY;
   alert('X = '+x+',Y = '+y);
}

Ver ejemplo 1

Un simple evento: arrastra un elemento cuando mueves el dedo:

function touchMove(event) {
   event.preventDefault();
   var touch = event.touches[0];
   var node = touch.target;
   node.style.position = "absolute";
   node.style.left = touch.pageX + "px";
   node.style.top = touch.pageY + "px";
}

Ver ejemplo 2


Detalle: por defecto, si arrastras un dedo sobre la pantalla es probable que la página comience a moverse (peor si ésta tiene scroll). Por suerte agregaron la función preventDefault() que hace que la página se quede quieta si lo necesitamos.

Las listas de eventos agrupan estos objetos, y contiene información para cada dedo que está tocando la pantalla. Además, contiene 2 otras listas: una que tiene información para los dedos que se originan del mismo elemento y otro que contiene sólo información para los dedos asociados al mismo evento. Estas listas están disponibles para cada evento touch, y son:

touches
<dd>
  una lista para cada dedo que est&aacute; posado actualmente sobre la pantalla.
</dd>

<dt>
  targetTouches
</dt>

<dd>
  tal como <strong>touches</strong>, pero filtra s&oacute;lo la informaci&oacute;n para los dedos que comienzan del mismo elemento.
</dd>

<dt>
  changedTouches
</dt>

<dd>
  lista la informaci&oacute;n para cada dedo involucrado en el mismo evento.
</dd>

Las propiedades que contienen estas listas son:

clientX
<dd>
  coordenada X del toque relativa al <em>viewport</em> (pantalla visible).
</dd>

<dt>
  clientY
</dt>

<dd>
  coordenada Y del toque relativa al <em>viewport</em>.
</dd>

<dt>
  screenX
</dt>

<dd>
  coordenada X relativa a la pantalla.
</dd>

<dt>
  screenY
</dt>

<dd>
  coordenada Y relativa a la pantalla.
</dd>

<dt>
  pageX
</dt>

<dd>
  coordenada X relativa a la p&aacute;gina completa (incluye <em>offset</em> del <em>scroll</em>).
</dd>

<dt>
  pageY
</dt>

<dd>
  coordenada Y relativa a la p&aacute;gina completa.
</dd>

<dt>
  target
</dt>

<dd>
  elemento donde el evento touch fue originado.
</dd>

<dt>
  indentifier
</dt>

<dd>
  n&uacute;mero identificados, &uacute;nico para cada evento <em>touch</em>.
</dd>

Para entender mejor, veamos el siguiente caso:

  1. Cuando pongo un dedo en la pantalla, las 3 listas tendrán la misma información en sus propiedades, pero changedTouches fue el que originó el evento.

  2. <li>
      <p>
        Cuando pongo el segundo dedo, <strong>touches</strong> tendr&aacute; 2 items (uno para cada dedo); <strong>targetTouches</strong> tendr&aacute; 2 items s&oacute;lo si el segundo dedo es posado en el mismo elemento del primero; <strong>changedTouches</strong> tendr&aacute; informaci&oacute;n relacionada al segundo dedo, porque fue lo que caus&oacute; el evento.
      </p>
    </li>
    
    <li>
      <p>
        Si pongo 2 dedos exactamente al mismo tiempo, tendr&eacute; 2 items en <strong>changedTouches</strong>: uno para cada dedo.
      </p>
    </li>
    
    <li>
      <p>
        Si muevo mis dedos, la &uacute;nica lista que cambiar&aacute; es <strong>changedTouches</strong> y va a tener informaci&oacute;n relacionada a cada dedo que se vaya moviendo (al menos uno).
      </p>
    </li>
    
    <li>
      <p>
        Cuando levanto un dedo, ser&aacute; eliminado de <strong>touches</strong> y <strong>targetTouches</strong> y aparecer&aacute; en <strong>changedTouches</strong> ya que fue el que origin&oacute; el evento.
      </p>
    </li>
    
    <li>
      <p>
        Si quito el &uacute;ltimo dedo se vaciar&aacute;n <strong>touches</strong> y <strong>targetTouches</strong>, y <strong>changedTouches</strong> tendr&aacute; la informaci&oacute;n para ese ultimo dedo.
      </p>
    </li>
    

Eventos Gestuales

<p>
  Eventos <em>multitouch</em> pueden ser combinados para crear eventos de gestos. Los objetos <em>GestureEvent</em> son enviados durante una secuencia <em>multitouch</em> y contienen informaci&oacute;n de dimensiones y rotaciones.
</p>

<p>
  Para registrarlos en <strong>HTML</strong>:
</p>
<div
   ongesturestart="gestureStart(event);"
   ongesturechange="gestureChange(event);"
   ongestureend="gestureEnd(event);"
>

Y mediante Javascript:

element.addEventListener("gesturestart", gestureStart, false);
element.addEventListener("gesturechange", gestureChange, false);
element.addEventListener("gestureend", gestureEnd, false);

Comencemos con un ejemplo simple:

function gestureStart(event) {
   <span class="commentjs">// tomamos el angulo y tamaño del elemento</span>
   var angle = event.rotation;
   var scale = event.scale;
   alert('angulo: '+angle+', dimension: '+scale);
}

Ver Ejemplo 3

Ahora escalamos y rotamos un elemento:

function gestureChange(event) {
   event.preventDefault();
   event.target.style.width = (200 * event.scale) + "px";
   event.target.style.height = (200 * event.scale) + "px";
   event.target.style.webkitTransform = 'rotate(' + event.rotation + 'deg)';
}

Ver Ejemplo 4

Creo que esto es un buen comienzo para que te interese esta plataforma, la que implementa un tipo de interacción háptica poco usual y con un gran potencial comercial.

Links: