2010-09-12 8 views
6

En una UIWebView (multi-touch habilitada) obtuve una página con dos divs (div1 y div2), cada uno de ellos registrado para los eventos touchstart y touchend. Cada vez que están recibiendo eventos de toque, estoy de dumping del contenido de:Problema de Webkit iphone/ipad con mutl-touch

  • event.touches: Contiene todos los actuales toques
  • event.targetTouches: contiene toques pertinentes a la meta dado
  • evento. changedTouches: contiene toques de haber activado el evento

cuenta la situación siguiente:

  • golpecito en div1: event.touches contiene div1
  • sin liberar div1, toque en div2: event.touches contiene div1 y div2
  • div2 liberación pero no div1: event.touches está vacía, lo que debería no como div1 todavía se está presionando. También div1 recibió un evento touchend como si hubiera sido liberado
  • espere un momento, aún teniendo div1 presionado, y recibirá un nuevo evento de inicio táctil, que no tiene sentido ya que nunca se ha lanzado.

Básicamente, al soltar un dedo, actúa como si se hubieran extraído ambos dedos. ¿Me estoy perdiendo de algo?

+0

tropecé con el mismo tema, en un iPod. Utilizo JavaScript, por lo que el problema parece ser bastante básico (error o malentendido de nuestro lado ;-). – mar10

+0

sí Estoy sorprendido de conocer un problema así porque este es bastante grande, el multi-touch es casi inutilizable en este contexto. Espero que nos falta algo ... – Alio

+0

Creo que he encontrado el mismo problema? http://stackoverflow.com/questions/3666929/mobile-sarai-touchend-event-not-firing-when-last-touch-is-removed puede confirmar? –

Respuesta

0

Sí, he encontrado esto también. Parece que debería ser un error, pero no estoy seguro.

La forma más flexible que he encontrado para hacer todo tipo de bondad multi-touch en Ios WebKit es capturar eventos de toque sobre la totalidad documento, es decir, llamar document.addEventListener() para todas las variedades de eventos táctiles que le interesan.

Luego use alguna táctica para descubrir en qué elemento ocurrió el contacto. Puede:

  • Examine la propiedad del tacto target para conseguir algo de información sobre el elemento. Sin embargo (¿otro posible error?), No puede encontrar el ID del elemento de esta propiedad, solo su clase, lo cual no es bueno para distinguir entre múltiples elementos usando la misma clase. Examine la fuente de this JS virtual light table for iOs para ver esto en acción.

  • Compara las coordenadas pageX y pageY del toque, con las dimensiones y posiciones de cada uno de los elementos con los que se relaciona el tacto (en relación con el documento). Por ejemplo, usando jQuery:

    var x = touch.pageX; 
    var y = touch.pageY; 
    var offset=$(element).offset(); 
    if (x >= offset.left && y >= offset.top && x < (offset.left + $(element).width()) && y < (offset.top + $(element).height())) 
    { 
        // element was touched! 
    } 
    

Usando este método, todas las acciones táctiles se comportan en su totalidad, como era de esperar :)

+0

Si lo entiendo correctamente, esto no ayuda en mi caso: quiero rastrear dos toques independientes en un solo elemento. – mar10

+0

Esto te ayudará con eso; puede realizar el seguimiento de todos los toques que desee en toda la página, en tantos elementos como desee. – funkybro

+0

sí, pero como menciono en la otra respuesta, tan pronto como se levanta un dedo, usted no sabe qué dedo ha sido lanzado como todos sus elementos recibirán un touchend incluso con toques vacías. Si esto no tiene importancia para el uso que quieres hacer de multitáctil, entonces está bien, si es importante, entonces olvídate de Webkit mientras este error esté dentro. Parece que quieres rastrear toques en el mismo elemento, por lo que deberías estar bien. – Alio

1

Gracias por su comentario funkybro pero desafortunadamente stil puede observar la misma errónea comportamiento al interceptar eventos táctiles a nivel de documento.Aquí es un rastro de lo que está sucediendo:

finger 1 touches elem1: 
20:44:00.130 onTouchStart: 
    touches len=1 (elem1) 
    changedTouches len=1 (elem1) 

finger 2 touches elem2 (finger 1 still presses elem1 and has not been released): 
20:44:01.066 onTouchStart: 
    touches len=2 (elem1,elem2) 
    changedTouches len=1 (elem2) 

finger 2 being released (finger 1 still presses elem1 and has not been released): 
this is where things begin to go wrong: we receive two touchend events consecutively for 
both elem1 and elem2,even though finger 1 is still holding on elem1 and has never released it. 
Also the event.touches array is empty for both events, which is wrong since elem1 is still 
being pressed. 
20:44:08.241 onTouchEnd: touches len=0 
       changedTouches len=1 (elem1) 

20:44:08.251 onTouchEnd: touches len=0 
       changedTouches len=1 (elem2) 

after 4 seconds in the same position (finger 1 pressed on elem1, finger 2 released), 
we receive a new touchstart event, as if the system wanted to undo the previous mistake 
and put things back into a consistent state. 
20:44:12.511 onTouchStart: 
    touches len=1 (elem1) 
    changedTouches len=1 (elem1) 

now releasing finger 1 from elem1, we receive the touchend event 
20:44:14.751 onTouchEnd: 
    touches len=0 
    changedTouches len=1 (elem1) 

Editar: Aquí está un ejemplo de código, para funcionar en Safari Mobile o dentro de su propia UIWebView en el dispositivo (no simulador).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>Multi-touch test</title> 
    <style type="text/css"> 
     div.square { 
      position:absolute; 
      width:80px; 
      height:80px; 
      opacity:0.5; 
     } 
     div#elem1 { 
      left:50px; 
      top:50px; 
      background-color:red; 
     } 
     div#elem2 { 
      left:200px; 
      top:50px; 
      background-color:green; 
     } 
     textarea#logger { 
      position:absolute; 
      width100%; 
      height:70%; 
      top:30%; 
      background-color:grey; 
      color:white; 
      overflow: scroll; 
     } 
    </style> 

    <script type="text/javascript"> 
    function log(text) { 
     logger.value = logger.value + text; 
     logger.scrollTop = logger.scrollHeight; 
    } 

    function touchesDumpStr(touches,logPrefix) { 
     var str = logPrefix + ', count=' + touches.length + ':'; 
     for (var i=0; i<touches.length; ++i) { 
      if (typeof touches[i].target.customName != 'undefined') { 
       str += touches[i].target.customName +' '; 
      } 
     } 
     str += '\n'; 
     return str; 
    } 

    function onTouchStart(e) { 
     log('onTouchStart\n'); 
     log(touchesDumpStr(e.touches, 'touches')); 
     log(touchesDumpStr(e.targetTouches, 'targetTouches')); 
     log(touchesDumpStr(e.changedTouches, 'changedTouches')); 
     for (var i=0; i<e.changedTouches.length; ++i) { 
      e.changedTouches[i].target.style.opacity=1.0; 
     } 
     e.preventDefault(); 
    } 

    function onTouchEnd(e) { 
     log('onTouchEnd\n'); 
     log(touchesDumpStr(e.touches, 'touches')); 
     log(touchesDumpStr(e.targetTouches, 'targetTouches')); 
     log(touchesDumpStr(e.changedTouches, 'changedTouches')); 
     for (var i=0; i<e.changedTouches.length; ++i) { 
      e.changedTouches[i].target.style.opacity=0.5; 
     } 
     e.preventDefault(); 
    } 

    var logger; 
    function init() { 
     logger = document.getElementById('logger'); 
     document.getElementById('elem1').customName='elem1'; 
     document.getElementById('elem2').customName='elem2'; 
     document.addEventListener("touchstart", onTouchStart, false); 
     document.addEventListener("touchend", onTouchEnd, false); 
    } 
    </script> 
</head> 
<body onload="init();"> 
    <div class="square" id="elem1"></div> 
    <div class="square" id="elem2"></div> 
    <textarea id="logger" rows="10" cols="45" readonly></textarea> 
</body> 
</html> 
+0

Idealmente, esto debería ser una adición a su respuesta original, o una respuesta a mi comentario, no una respuesta en sí misma. – funkybro

+0

derecha, lo siento por esto ... – Alio

+0

yo no entiendo muy bien su depuración, pero parece que todavía tiene oyentes unidos a cada elemento individual, esto es lo que está causando el comportamiento que se observa. ¿Puedes pegar pequeños fragmentos relevantes de código real en tu pregunta? – funkybro

0

Tengo una solución, pero no es óptima. Mantenga un registro de touch.identifier cuando se inicie el evento touchstart. Cuando obtienes un evento touchend setinterval de 500ms. Si durante el intervalo se han disparado otro touchend y un touchstart, compruebe si el touchstart tiene un identificador táctil existente y puede determinar qué dedo levantó.

Cuando dos dedos están abajo no hay manera de determinar en el momento de la primera touchend el que ha levantado el dedo. He revisado el orden de las modificaciones cambiadas, he comprobado una copia guardada de los eventos de inicio táctil. He visto los eventos de gestos que preceden al fallo. La demora en el toque repetido del dedo restante depende de un disparo de la palanca táctil.

Si este error está reventando su interacción multi-touch, vaya añadir información a esta descripción claramente errónea de la secuencia de eventos en la documentación para desarrolladores. GestureEvent Class Reference

0

Parece que este problema se resolvió en IOS 4.2 (no pude reproducirlo en un iPhone 4 con iOS 4.2.1)

+0

iOS 4.2 ha mejorado las cosas, pero esto no está completamente solucionado. Según el tiempo y la cantidad de elementos que se presionen, puede aparecer un retraso. – Alio

Cuestiones relacionadas