2011-08-17 14 views
17

Estoy jugando con touchstart y eventos touchend en mi iPhone. Construí una página de muestra que tiene div que si la tocas y desplazas la página, debería devolver las coordenadas y de las posiciones inicial y final.jQuery (Swipe vs. Touch) pageX y pageY siguen regresando 0

enlace: http://jsbin.com/ibemom/2

el jQuery:

var touchStartPos; 

$('.theDiv') 
    .bind('touchstart', function(e){ 
    touchStartPos = e.pageY; 
    }) 
    .bind('touchend', function(e){ 
    alert(touchStartPos + ' | ' + e.pageY) 
    }) 

Cuando me carga la página en mi iPhone, sin embargo, mantiene la alerta informar tanto los valores como cero. ¿Alguien ve algo mal con lo que tengo?

ACTUALIZACIÓN:

me encontré con este fragmento de código en el proyecto jQuery Mobile: https://github.com/jquery/jquery-mobile/issues/734

Un comentario que de ella sobresalía:

// (in iOS event.pageX and event.pageY are always 0) 

no dice qué ese es el caso, pero al menos encontré a alguien más que ve lo mismo. Examinará el código de muestra en esa página para ver si la solución está allí.

ACTUALIZACIÓN II:

Bueno, después de mirar a través del código de ejemplo en el enlace de arriba, parece que esto va a devolver un valor real:

e.originalEvent.touches[0].pageY 

El problema es, ahora me doy cuenta de que no es todo lo que necesito. Devuelve el desplazamiento en Y del área que toqué dentro del objeto al que adjunté el evento a EN RELACIÓN CON EL DOCUMENTO HTML ... en lugar de a la ventana del navegador.

Mi objetivo es determinar en qué parte de la pantalla comenzó el toque y dónde terminó ... y luego comparar los valores. Si son bastante diferentes, supongamos que se realizó un deslizamiento ... en lugar de un toque.

ACTUALIZACIÓN III:

también estoy encontrar referencias a estos ejemplos:

e.originalEvent.touches[0].pageX 

event.targetTouches[0].pageY 

A pesar de que parece que no puede conseguir los que trabajar bien. Ambos devuelven errores indefinidos.

ACTUALIZACIÓN IV:

Parece que una solución es derrota desplazada() en el propio documento. Puedo aplicar un evento touchend al documento y luego verificar su compensación.

El problema con esto es que mi evento touchend primero se activará en el elemento en mi página y ENTONCES lo disparará en el documento (burbujeo). Por lo tanto, no puedo determinar si fue un toque o deslizar ANTES de que deba averiguar qué hacer en el evento touchend de los objetos.

Aún ponderando éste ...

+0

raro, no knwo sobre los móviles, pero funciona con clics http://jsfiddle.net/nH2PU/ – Sinetheta

+1

Estaba esperando que esto no iba a ser esto mucho de un stumper. ;) –

+0

Lo mismo parece estar sucediendo en Android (2.2.2) – NoBugs

Respuesta

19

Ok La respuesta rápida es que no se puede detectar un toque cuando el dedo sale de la pantalla (touchend).

Mi primer ejemplo demuestra que: http://jsfiddle.net/Y4fHD/

ahora a la solución. O llámalo como quieras. Tal vez tenga sentido no detectar en el evento touchend porque el toque tiene terminado.

Enlace el manejador del evento touchmove: http://jsfiddle.net/Y4fHD/1/

var endCoords = {}; 
$(document.body).bind("touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

Y a continuación, utilizar la variable endCoords para determinar el último toque

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY); 
}); 

intento Ok a sólo toque su dispositivo! Entonces el error todavía ocurrirá: ¿Por qué? Porque no has movido tu toque.

Si tenemos todo listo en el touchstart define la variable de endCoords estamos allí: http://jsfiddle.net/Y4fHD/2/

var endCoords = {}; 
$(document.body).bind("touchstart touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

Y a continuación, utilizar la variable endCoords para determinar el último toque

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY); 
}); 

Ahora tratar de aprovechar su ¡dispositivo!

Algunas notas finales serán: Make a variables: startCoords y endCoords luego utilizar estos en caso touchend: http://jsfiddle.net/Y4fHD/3/

var startCoords = {}, endCoords = {}; 
$(document.body).bind("touchstart", function(event) { 
    startCoords = endCoords = event.originalEvent.targetTouches[0]; 
}); 
$(document.body).bind("touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 
$(document.body).bind("touchend", function(event) { 
    $('p').text("Your touch on the axis: " + Math.abs(startCoords.pageX-endCoords.pageX) + "x, " + Math.abs(startCoords.pageY-endCoords.pageY) + "y"); 
}); 

Nota:
Ninguno de los ejemplos anteriores se ponen a prueba, las esperanzas que funciona!
Math.abs me da el valor absoluto de un número, por ejemplo: -5 convierte en 5

+0

Encontré que en el último ejemplo, escribió el valor absoluto para el eje Y dos veces en la línea "$ ('p'). Text (" Su toque en el eje ... " – Arabam

+0

@Arabam Esto ya está solucionado. Pensar que después de dos años se encontrará ese tipo de error :) – andlrc

+0

Gracias por mencionar' event.originalEvent' - en Android el evento original estaba suprimiendo la propiedad targetTouches y rompiendo todo! Curiosamente, no era un problema en iOS, lo que dificultaba la depuración. – jocull

1

Aquí es lo que funciona para mí .... pieza

$('.someClass').bind('touchmove',function(e){ 
    e.preventDefault(); 
    var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; 
    var elm = $(this).offset(); 
    var x = touch.pageX - elm.left; 
    var y = touch.pageY - elm.top; 
    if(x < $(this).width() && x > 0){ 
     if(y < $(this).height() && y > 0){ 
       //your code here 
     } 
    } 
}); 
2

No se simplifica de código que estoy acostumbrado a detectar deslizar gestos para .myelement, en el original era galería deslizante

$(function() { 
    var diff, tchs, del = 150, 
    clk = function(el){ 
     if (typeof(tchs) !== 'object') return; //we have nothing to do 
     if ((diff - tchs[tchs.length - 1].pageX) < 0) { //swipe right 

     } 
     else if ((diff - tchs[tchs.length - 1].pageX) > 0) { //swipe left 

     } 
    }; 
    $('.myelement').bind('touchstart touchmove', function(ev){ 
      var oev = ev.originalEvent, el = $(this); 
      switch(ev.type.charAt(5)){ 
       case 's': //touch start 
        diff = oev.pageX; 
        window.setTimeout(clk, del, el); 
       break; 
       case 'm': //touch move 
        tchs = oev.touches; 
       break; 
      } 
    }); 
}); 

UPD: por cierto, cuando utilicé la versión de software MobiOne 2.0.0M2 Centro de Pruebas de que había puesto el valor pageX touchend como se esperaba, por lo que suena licenciado en Letras d implementación que puede confundir fácilmente si no tienes acceso rápido a un dispositivo real.

UPD2: bueno, inspirado por los comentarios positivos :) se dio cuenta de la versión poco complicada, que permite detectar los deslizamientos derecho, izquierdo, arriba y abajo, pero hay que limpiarlo, pero ya entendió la idea. respuesta

$(function() { 
    var ftch, // first touch cache 
    lck = Math.sin(Math.PI/4); //lock value, sine of 45 deg configurable 

    var defSwipeDir = function (el, tchs) { // need define swaping direction, for better UX 
     if (typeof (tchs) !== 'object') return 0; // check if there was any movements since first touch, if no return 0 
     var ltch = tchs[tchs.length - 1], // last touch object 
      dx = ltch.pageX - ftch.pageX, 
      dy = ltch.pageY - ftch.pageY, 
      hyp = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)), 
      sin = dy/hyp, 
      cos = dx/hyp, 
      dir; 

     if (Math.abs(cos) >= lck) { // left or right swape 
      dir = cos > 0 ? 'r' : 'l'; 
     } else { // up or down 
      dir = sin < 0 ? 'u' : 'd'; 
     } 
     el.trigger('swipe', dir); // trigger custom swipe event 
     return dir; // and return direction too 
    } 

    $('.myelementTouchDetection').on('touchstart touchmove swipe', function (ev, d) { 
     var oev = ev.originalEvent, 
      myelementTouchDetection = $(this), 
      dir; // you may know swipes on move event too 

     switch (ev.type) { 
      case 'touchstart': 
       ftch = oev; 
       break; 
      case 'touchmove': 
       dir = defSwipeDir(myelementTouchDetection, oev.touches); 
       return false // cancel default behaiviour 
       break; 
      case 'swipe': 
       switch (d) { 
        case 'r': // swipe right 
         console.log('swipe right'); 
         break; 
        case 'l': // swipe left 
         console.log('swipe left'); 
         break; 
        case 'u': // swipe up 
         console.log('swipe up'); 
         break; 
        case 'd': // swipe down 
         console.log('swipe down'); 
         break; 
       } 
       break; 
     } 
    }) 
}); 
2

de NULL, anteriormente, funcionó muy bien para mí, excepto que no se puede asignar a startCoords endCoords en la función touchstart de ruedas. Luego señalan el mismo objeto para que cuando endCoords se actualice, también lo haga startCoords. Cuando el evento touchend se activa, startCoords siempre igualará a endCoords.

Código actualizado a continuación. Esto funcionó para mí en un iPad 3 usando Safari en iOS 6.0. Editado también para corregir un error matemático y de visualización y eliminar Math.abs() dentro de la función vinculada a touchend. También se agregó una llamada a event.preventDefault() dentro de la función touchmove-bound, para que estos también funcionen en Google Chrome en iOS.

var startCoords = {}, endCoords = {}; 

$(document.body).bind("touchstart", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
    startCoords.pageX = event.originalEvent.targetTouches[0].pageX; 
    startCoords.pageY = event.originalEvent.targetTouches[0].pageY; 
}); 

$(document.body).bind("touchmove", function(event) { 
    event.preventDefault(); 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your touch on the axis: " + (endCoords.pageX-startCoords.pageX) + "x, " + (endCoords.pageY-startCoords.pageY) + "y"); 
});