Comment distinguer la souris "clic" et " glisser"

J'utilise jQuery.click pour gérer l'événement de clic de souris sur Raphael graph, pendant ce temps, je dois gérer l'événement de la souris drag, le glisser de la souris se compose de mousedown, mouseupet mousemove dans Raphaël.

Il est difficile de distinguer click et drag parce que click contiennent égalementmousedown & mouseup, Comment puis-je distinguer la souris "clic" et la souris "glisser" puis en Javascript?

121
demandé sur Greg 2011-05-18 13:00:30

8 réponses

Je pense que la différence est qu'il est un mousemove entre mousedown et mouseup en faisant un glisser, mais pas en un clic.

, Vous pouvez faire quelque chose comme ceci:

var flag = 0;
var element = xxxx;
element.addEventListener("mousedown", function(){
    flag = 0;
}, false);
element.addEventListener("mousemove", function(){
    flag = 1;
}, false);
element.addEventListener("mouseup", function(){
    if(flag === 0){
        console.log("click");
    }
    else if(flag === 1){
        console.log("drag");
    }
}, false);
158
répondu wong2 2012-04-01 00:34:07

Si vous utilisez déjà jQuery:

var $body = $('body');
$body.on('mousedown', function (evt) {
  $body.on('mouseup mousemove', function handler(evt) {
    if (evt.type === 'mouseup') {
      // click
    } else {
      // drag
    }
    $body.off('mouseup mousemove', handler);
  });
});
29
répondu Gustavo Rodrigues 2013-12-30 00:28:49

Cela devrait bien fonctionner. Similaire à la réponse acceptée (bien qu'en utilisant jQuery), mais l'indicateur isDragging n'est réinitialisé que si la nouvelle position de la souris diffère de celle de l'événement mousedown. Contrairement à la réponse acceptée, cela fonctionne sur les versions récentes de Chrome, où mousemove est déclenché indépendamment du fait que la souris ait été déplacée ou non.

var isDragging = false;
var startingPos = [];
$(".selector")
    .mousedown(function (evt) {
        isDragging = false;
        startingPos = [evt.pageX, evt.pageY];
    })
    .mousemove(function (evt) {
        if (!(evt.pageX === startingPos[0] && evt.pageY === startingPos[1])) {
            isDragging = true;
        }
    })
    .mouseup(function () {
        if (isDragging) {
            console.log("Drag");
        } else {
            console.log("Click");
        }
        isDragging = false;
        startingPos = [];
    });

Vous pouvez également ajuster la vérification des coordonnées dans mousemove Si vous voulez ajouter un peu de tolérance (c'est-à-dire traiter les petits mouvements comme des clics, pas des traînées).

13
répondu nirvana-msu 2017-11-29 08:05:31

Comme le souligne mrjrdnthms dans son commentaire sur la réponse acceptée, cela ne fonctionne plus sur Chrome (il déclenche toujours le mousemove), j'ai adapté la réponse de Gustavo (puisque j'utilise jQuery) pour traiter le comportement de Chrome.

var currentPos = [];

$(document).on('mousedown', function (evt) {

   currentPos = [evt.pageX, evt.pageY]

  $(document).on('mousemove', function handler(evt) {

    currentPos=[evt.pageX, evt.pageY];
    $(document).off('mousemove', handler);

  });

  $(document).on('mouseup', function handler(evt) {

    if([evt.pageX, evt.pageY].equals(currentPos))
      console.log("Click")
    else
      console.log("Drag")

    $(document).off('mouseup', handler);

  });

});

La Fonction Array.prototype.equals provient de cette réponse

12
répondu Francisco Aquino 2017-05-23 12:26:32

Si vous avez envie d'utiliser Rxjs :

var element = document;

Rx.Observable
  .merge(
    Rx.Observable.fromEvent(element, 'mousedown').mapTo(0),
    Rx.Observable.fromEvent(element, 'mousemove').mapTo(1)
  )
  .sample(Rx.Observable.fromEvent(element, 'mouseup'))
  .subscribe(flag => {
      console.clear();
      console.log(flag ? "drag" : "click");
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.4.1/dist/global/Rx.js"></script>

C'est un clone direct de ce que @wong2 a fait dans sa réponse, mais converti en RxJs.

Aussi intéressant d'utiliser de sample. Le sample exploitant doit prendre la dernière valeur de la source (merge de mousedown et mousemove) et émettre lors de l'intérieure observables (mouseup) émet.

8
répondu Dorus 2018-08-19 07:58:47

Nettoyeur ES2015

let drag = false;

document.addEventListener('mousedown', () => drag = false);
document.addEventListener('mousemove', () => drag = true);
document.addEventListener('mouseup', () => console.log(drag ? 'drag' : 'click'));

N'a rencontré aucun bug, comme d'autres le commentent.

3
répondu Przemek 2018-08-19 07:51:52

En utilisant jQuery avec un 5 pixel x/y theshold pour détecter le glisser:

var dragging = false;
$("body").on("mousedown", function(e) {
  var x = e.screenX;
  var y = e.screenY;
  dragging = false;
  $("body").on("mousemove", function(e) {
    if (Math.abs(x - e.screenX) > 5 || Math.abs(y - e.screenY) > 5) {
      dragging = true;
    }
  });
});
$("body").on("mouseup", function(e) {
  $("body").off("mousemove");
  console.log(dragging ? "drag" : "click");
});
2
répondu silverwind 2017-05-26 07:15:53

Si juste pour filtrer le cas de glisser, faites-le comme ceci:

var moved = false;
$(selector)
  .mousedown(function() {moved = false;})
  .mousemove(function() {moved = true;})
  .mouseup(function(event) {
    if (!moved) {
        // clicked without moving mouse
    }
  });
2
répondu jqgsninimo 2018-02-21 08:52:46