Detectar izquierda / derecha-deslizar en los dispositivos táctiles, pero permitir arriba / abajo-desplazamiento


Necesito detectar y reaccionar a los golpes de izquierda/derecha, pero quiero darle al usuario la capacidad de desplazarse en el mismo elemento, por lo que siempre y cuando mueva su dedo solo a la izquierda/derecha con un movimiento máximo hacia arriba/hacia abajo de X píxeles, no debe desplazarse, pero cuando excede X, debe desplazarse.

Así que lo que hice fue:

var startX, startY, $this = $(this);
function touchmove(event) {
        var touches = event.originalEvent.touches;
        if (touches && touches.length) {
            var deltaX = touches[0].pageX - startX;
            var deltaY = touches[0].pageY - startY;
            if (Math.abs(deltaY) > 50) {
                $this.html('X: ' + deltaX + '<br> Y: ' + deltaY + '<br>TRUE');
                $this.unbind('touchmove', touchmove);
                return true;
            } else {
                $this.html('X: ' + deltaX + '<br> Y: ' + deltaY);
                event.preventDefault();
            }
        }
    }

    function touchstart(event) {
        var touches = event.originalEvent.touches;
        if (touches && touches.length) {
            startX = touches[0].pageX;
            startY = touches[0].pageY;
            $this.bind('touchmove', touchmove);
        }
        //event.preventDefault();
    }

Pero no restaura la capacidad de desplazarse en el caso "if"...

Gracias por cualquier consejo.

Author: Raphael Jeger, 2013-07-10

4 answers

Escribí mis propios eventos de controlador táctil.tal vez esto te ayude

Comprueba:

Clic rápido : 'fc'

Desliza hacia la izquierda:'swl'

Deslice hacia la derecha : 'swr'

Deslizar hacia arriba : 'swu'

Deslizar hacia abajo:'swd'

Cada comprobación inicializa su evento correspondiente.pero puedes desplazarte y hacer cualquier otra cosa que hagas normalmente. solo tienes nuevos eventos.

Necesita swl swr, también sugiero usar fc (fastclick) para eventos de clic... es mucho más rápido que clic normal.

window.onload=function(){
(function(d){
 var
 ce=function(e,n){var a=document.createEvent("CustomEvent");a.initCustomEvent(n,true,true,e.target);e.target.dispatchEvent(a);a=null;return false},
 nm=true,sp={x:0,y:0},ep={x:0,y:0},
 touch={
  touchstart:function(e){sp={x:e.touches[0].pageX,y:e.touches[0].pageY}},
  touchmove:function(e){nm=false;ep={x:e.touches[0].pageX,y:e.touches[0].pageY}},
  touchend:function(e){if(nm){ce(e,'fc')}else{var x=ep.x-sp.x,xr=Math.abs(x),y=ep.y-sp.y,yr=Math.abs(y);if(Math.max(xr,yr)>20){ce(e,(xr>yr?(x<0?'swl':'swr'):(y<0?'swu':'swd')))}};nm=true},
  touchcancel:function(e){nm=false}
 };
 for(var a in touch){d.addEventListener(a,touch[a],false);}
})(document);
//EXAMPLE OF USE
var h=function(e){console.log(e.type,e)};
document.body.addEventListener('fc',h,false);// 0-50ms vs 500ms with normal click
document.body.addEventListener('swl',h,false);
document.body.addEventListener('swr',h,false);
document.body.addEventListener('swu',h,false);
document.body.addEventListener('swd',h,false);
}

En este caso h es mi manejador para cada tipo de evento y añado los manejadores al cuerpo.

Para lo que entiendo su pregunta solo tiene que escribir

YOURELEMENT.addEventListener('swr',YOURSWIPERIGHTFUNCTION,false);
YOURELEMENT.addEventListener('swl',YOURSWIPELEFTFUNCTION,false);

Para manejar múltiples elementos y la misma función... solo agrega un manejador.

Así que si tienes

<ul id="ul"><li>1</li><li>2</li><li>3</li></ul>

Lo haces:

var deleteli=function(e){
 var li=e.target;
 console.log('deleting '+li.textContent);
}
document.getElementById('ul').addEventListener('swl',deleteli,false);

Lo mismo para fc y swr

Hay un error en ios: no use alert() .. se ejecutará 2 veces.

 41
Author: cocco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-11 10:37:10

Hay un "bug" en la respuesta aceptada. Si no usas Chrome en Android, sino el navegador integrado o una "webview" (para una aplicación híbrida html5), por ejemplo, no se detecta el deslizamiento.

Descubrí que el evento no se dispara, debido al comportamiento normal del desplazamiento. Así que agregar " e. preventDefault ();" en touchmove lo arreglaría o lo arreglaría Eric Fuller en la respuesta aceptada.

Es un buen recorte, pero en una aplicación web móvil o sitio web esto podría resultar en un mal desplazamiento tartamudeo, porque los eventos táctiles se observan todo el tiempo.

Así que decidí construir algo nuevo. No es tan cómodo como tener nuevos oyentes de eventos, pero es lo suficientemente cómodo para mis necesidades y es performat.

function detectswipe(el,func) {
  swipe_det = new Object();
  swipe_det.sX = 0;
  swipe_det.sY = 0;
  swipe_det.eX = 0;
  swipe_det.eY = 0;
  var min_x = 20;  //min x swipe for horizontal swipe
  var max_x = 40;  //max x difference for vertical swipe
  var min_y = 40;  //min y swipe for vertical swipe
  var max_y = 50;  //max y difference for horizontal swipe
  var direc = "";
  ele = document.getElementById(el);
  ele.addEventListener('touchstart',function(e){
    var t = e.touches[0];
    swipe_det.sX = t.screenX; 
    swipe_det.sY = t.screenY;
  },false);
  ele.addEventListener('touchmove',function(e){
    e.preventDefault();
    var t = e.touches[0];
    swipe_det.eX = t.screenX; 
    swipe_det.eY = t.screenY;    
  },false);
  ele.addEventListener('touchend',function(e){
    //horizontal detection
    if ((((swipe_det.eX - min_x > swipe_det.sX) || (swipe_det.eX + min_x < swipe_det.sX)) && ((swipe_det.eY < swipe_det.sY + max_y) && (swipe_det.sY > swipe_det.eY - max_y)))) {
      if(swipe_det.eX > swipe_det.sX) direc = "r";
      else direc = "l";
    }
    //vertical detection
    if ((((swipe_det.eY - min_y > swipe_det.sY) || (swipe_det.eY + min_y < swipe_det.sY)) && ((swipe_det.eX < swipe_det.sX + max_x) && (swipe_det.sX > swipe_det.eX - max_x)))) {
      if(swipe_det.eY > swipe_det.sY) direc = "d";
      else direc = "u";
    }

    if (direc != "") {
      if(typeof func == 'function') func(el,direc);
    }
    direc = "";
  },false);  
}

myfunction(el,d) {
  alert("you swiped on element with id '"+el+"' to "+d+" direction");
}

Para usar la función simplemente úsala como

detectswipe('an_element_id',myfunction);

detectswipe('an_other_element_id',my_other_function);

Si se detecta un golpe,se llama a la función "myfunction" con el parámetro element-id y "l,r,u,d" (izquierda,derecha,arriba, abajo).

Ejemplo: http://jsfiddle.net/rvuayqeo/1/

 6
Author: EscapeNetscape,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-24 22:07:19

Todos estos códigos necesitan mejoras (como la mayoría de los códigos que puedes encontrar en la manipulación táctil).

Al jugar con el evento touch, tenga en cuenta que el usuario tiene más de un dedo, que un toque tiene un identificador y que la lista touches representa todos los toques actuales en la superficie, incluso los toques que no se han movido.

Así que el proceso es relativamente simple:

  1. Ontouchstart: obtener el primer toque cambiado (no event.originalEvent.touches propiedad, pero event.originalEvent.changedTouches uno). Registre su identificador con event.originalEvent.changedTouches[0].identifier y toque las propiedades para buscar (pageX/pageY o clientX/clientY que son bastante útiles en combinación con el método DOMElement.getBoundingClientRect() );

  2. Ontouchmove: asegúrese de que el toque actual esté en la lista changedTouches con event.originalEvent.changedTouches.identifiedTouch( identifier ). Si no devuelve nada, significa que el usuario ha movido otro toque (no el que está buscando). También registra propiedades táctiles para buscar y hacer lo que quieras con.

  3. Ontouchend: una vez más, debe estar seguro de que el toque actual está en la lista changedTouches. Haga el trabajo con propiedades táctiles y finalmente deseche su identificador táctil actual.

Si quieres hacerlo más fuerte, considera varios toques (no solo uno) para observar.

Más información sobre TouchEvent, TouchList y Touch on: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events

 2
Author: Loops,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-17 09:42:01

Detectando izquierda y derecha mientras el tacto está todavía en movimiento.

Esto se hace guardando la última posición y usando timeout para borrar la última posición después de touchmove stop.

var currentX;
var lastX = 0;
var lastT;
$(document).bind('touchmove', function(e) {
    // If still moving clear last setTimeout
    clearTimeout(lastT);

    currentX = e.originalEvent.touches[0].clientX;

    // After stoping or first moving
    if(lastX == 0) {
        lastX = currentX;
    }

    if(currentX < lastX) {
        // Left
    } else if(currentX > lastX){
        // Right
    }

    // Save last position
    lastX = currentX;

    // Check if moving is done
    lastT = setTimeout(function() {
        lastX = 0;
    }, 100);
});
 0
Author: Nebojsa Sapic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-24 03:37:13