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
, mouseup
et 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?
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);
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);
});
});
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).
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
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.
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.
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");
});
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
}
});