Détecte le glissement gauche / droite sur les appareils tactiles, mais permet de faire défiler vers le haut/vers le bas

j'ai besoin de détecter et de réagir à gauche/droite, mais je veux donner à l'utilisateur la possibilité de faire défiler sur le même élément, aussi longtemps qu'il déplace son doigt seulement gauche/droite avec un mouvement maximum haut/bas de x pixels, il ne devrait pas faire défiler, mais quand il dépasse X, il devrait faire défiler.

alors ce que j'ai fait c'est:

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();
    }

mais je ne restaure pas la capacité de faire défiler dans le cas "si"...

Merci pour tous les conseils.

25
demandé sur Raphael Jeger 2013-07-10 13:41:56

4 réponses

j'ai écrit mes propres évènements de handler tactile.peut-être que cela vous aide

il vérifie:

clic rapide: 'fc'

glisser à gauche: 'swl'

glisser à droite: 'swr'

faites défiler vers le haut : 'uts'

glisser vers le bas : 'swd'

chaque vérification initialise son événement correspondant.mais vous pouvez faire défiler et faire tout ce que vous faites normalement. vous avez juste quelques nouveautés.

vous avez besoin de SWL swr, je suggère d'utiliser fc (fastclick) pour les événements de clic... c'est beaucoup plus rapide qu'un 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);
}

dans ce cas, h est mon gestionnaire pour chaque type d'événement et j'ai ajouter des gestionnaires de l'organisme.

pour ce que je comprends de votre question, vous avez juste à écrire

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

pour gérer plusieurs éléments et la même fonction... il suffit d'ajouter un gestionnaire.

donc si vous avez

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

tu fais:

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

idem pour fc & swr

il n' est un bug dans ios: n'utilisez pas alert ().. il sera exécuté 2 fois.

41
répondu cocco 2017-08-11 10:37:10

il y a un "bug" dans la réponse acceptée. Si vous n'utilisez pas Chrome sur Android, mais la construire dans un navigateur ou un "webview" (html5-hybride-application) par exemple, le balayage n'est pas détecté.

j'ai découvert que l'événement ne démarre pas, à cause du comportement normal du scroll. Ainsi, l'ajout de "e.preventDefault();" dans touchmove serait-il fixer ou le correctif de Eric Fuller dans la accepté de répondre.

c'est un joli snipped mais dans une WebApp mobile ou un site Web cela pourrait en résulter dans un mauvais scroll bégaie, parce que les événements de toucher sont observés tout le temps.

alors j'ai décidé de construire quelque chose de nouveau. Ce n'est pas aussi confortable que d'avoir de nouveaux auditeurs, mais c'est assez confortable pour mes besoins et c'est 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");
}

pour utiliser la fonction il suffit de l'utiliser comme

detectswipe('an_element_id',myfunction);

detectswipe('an_other_element_id',my_other_function);

si un balayage est détecté,la fonction "myfunction" est appelée avec les paramètres element-id et "l,r,u,D" (left,right,up, down).

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

6
répondu EscapeNetscape 2014-11-24 22:07:19

tous ces codes doivent être améliorés (comme la plupart des codes que vous pouvez trouver sur la manipulation tactile).

lorsque vous jouez avec l'événement touch, gardez à l'esprit que l'Utilisateur a plus d'un doigt, qu'un contact a un identifiant et touches liste de représenter toutes les touches sur la surface, même touche qui n'ont pas bougé.

Donc, le processus est relativement simple:

  1. ontouchstart: obtenir le premier changé touch (pas event.originalEvent.touches propriété, mais event.originalEvent.changedTouches). Inscrire son identifiant event.originalEvent.changedTouches[0].identifier et toucher les propriétés à rechercher (pageX/pageY ou clientX/clientY qui sont assez utiles en combinaison avec DOMElement.getBoundingClientRect() méthode);

  2. ontouchmove: assurez-vous que la touche courante est dans la liste changedTouches avec event.originalEvent.changedTouches.identifiedTouch( identifier ). Si elle renvoie rien, cela signifie que l'utilisateur a déplacé une autre touch (pas celui que vous cherchez). Enregistrez aussi les propriétés tactiles pour chercher et faire ce que vous voulez avec.

  3. ontouchend: encore une fois, vous devez être sûr que la touche courante est dans la liste changedTouches. Faire le travail avec les propriétés touch et finalement jeter votre identifiant touch actuel.

si vous voulez le faire plus fort, envisagez plusieurs touches (pas une seule) à observer.

plus d'informations sur TouchEvent, TouchList et Contact sur: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events

2
répondu Loops 2014-01-17 09:42:01

détecter gauche et droite pendant que le toucher est toujours en mouvement.

ceci est fait avec la sauvegarde de la dernière position et en utilisant timeout pour effacer la dernière position après l'arrêt touchmove.

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
répondu Nebojsa Sapic 2017-04-24 03:37:13