swipeleft - jQuery(Swipe vs. Touch) pageX y pageY siguen regresando 0
swipeleft() (4)
Esto es lo que funciona para mí ...
$(''.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
}
}
});
Estoy jugando con los eventos de touchstart y touchend en mi iPhone. Construí una página de muestra que tiene div que, si la tocas y recorres la página, debería devolver las coordenadas y de las posiciones inicial y final.
enlace: http://jsbin.com/ibemom/2
la jQuery:
var touchStartPos;
$(''.theDiv'')
.bind(''touchstart'', function(e){
touchStartPos = e.pageY;
})
.bind(''touchend'', function(e){
alert(touchStartPos + '' | '' + e.pageY)
})
Sin embargo, cuando cargo esa página en mi iPhone, la alerta continúa reportando ambos valores como cero. ¿Alguien ve algo malo con lo que tengo?
ACTUALIZAR:
Me encontré con este fragmento de código en el proyecto de jQuery Mobile: https://github.com/jquery/jquery-mobile/issues/734
Un comentario de ella sobresalió:
// (in iOS event.pageX and event.pageY are always 0 )
No dice por qué ese es el caso, pero al menos encontré a alguien más que ve lo mismo. Revisará el código de muestra en esa página para ver si la solución está ahí.
ACTUALIZACIÓN II:
Bueno, después de mirar el código de muestra en el enlace anterior, parece que esto devolverá un valor real:
e.originalEvent.touches[0].pageY
El problema es que ahora me doy cuenta de que no es exactamente lo que necesito. Está devolviendo el desplazamiento Y del área que toqué dentro del objeto al que vinculé el evento EN RELACIÓN CON EL DOCUMENTO HTML ... en lugar de la ventana del navegador.
Mi objetivo es averiguar dónde comenzó el toque en la pantalla y dónde terminó ... y luego comparar los valores. Si son un poco diferentes, entonces suponemos que se realizó un deslizamiento ... en lugar de un toque.
ACTUALIZACIÓN III:
También estoy encontrando referencias a estos ejemplos:
e.originalEvent.touches[0].pageX
event.targetTouches[0].pageY
Aunque parece que tampoco puedo hacer que funcionen. Ambos devuelven errores indefinidos.
ACTUALIZACIÓN IV:
Parece que una solución es hacer un seguimiento de offset () en el propio documento. Puedo aplicar un evento de toque al documento y luego verificar su compensación.
El problema con esto es que mi evento de toque primero se activará en el elemento de mi página y ENTONCES lo disparará en el documento (burbujeo). Por lo tanto, no puedo realmente determinar si fue un toque o deslizar ANTES de que tenga que averiguar qué hacer en el evento de toque de objetos.
Todavía pensando en esto ...
Hay un fragmento de código simplificado que utilizo para detectar gestos de deslizamiento de .myelement, en el original era la galería de controles deslizantes
$(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é el software MobiOne versión 2.0.0M2 Centro de Pruebas, puse el valor de la página táctil como se esperaba, por lo que suena una mala implementación que puede confundirse fácilmente si no tiene acceso rápido al dispositivo real.
UPD2: está bien, inspirado en comentarios positivos :) se realizó una versión un poco complicada, que permite detectar swipes correctos, izquierdos, hacia arriba y hacia abajo, aún debe ser limpiado, pero tienes la idea.
$(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;
}
})
});
La respuesta de NULL, arriba, funcionó muy bien para mí, excepto que no puede asignar startCoords a endCoords en la función de enlace de inicio rápido. Luego señalan el mismo objeto para que cuando se actualice endCoords, también lo haga startCoords. Cuando el evento de toque se dispara, startCoords siempre será igual a endCoords.
Código actualizado a continuación. Esto me funcionó 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 de límite de touchend. También se agregó una llamada event.preventDefault () dentro de la función de enlace táctil, para que funcionen también 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");
});
Ok, la respuesta rápida es que no puedes 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 la detección en el evento de toque porque el toque ha terminado.
Enlazar el controlador en el evento touchmove
: http://jsfiddle.net/Y4fHD/1/
var endCoords = {};
$(document.body).bind("touchmove", function(event) {
endCoords = event.originalEvent.targetTouches[0];
});
Y luego usa 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);
});
Ok, intenta simplemente tocar tu dispositivo! Entonces el error todavía ocurrirá: ¿Por qué? Porque no has movido tu toque.
Si todos estamos listos en el touchstart
define la variable endCoords
, estamos allí: http://jsfiddle.net/Y4fHD/2/
var endCoords = {};
$(document.body).bind("touchstart touchmove", function(event) {
endCoords = event.originalEvent.targetTouches[0];
});
Y luego usa 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 intenta tocar tu dispositivo!
Algunas notas finales serán: Crear a las variables: startCoords
y endCoords
luego usarlas en el evento de 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 está probado, ¡espera que funcione!
Math.abs
me da el valor absoluto de un número, por ejemplo: -5 se convierte en 5