Как различить «щелчок мышью» и «перетаскивание» - PullRequest
144 голосов
/ 18 мая 2011

Я использую jQuery.click для обработки события щелчка мыши на графике Рафаэля, тем временем мне нужно обработать событие мыши drag, перетаскивание мыши состоит из mousedown, mouseup и mousemove в Рафаэле.

Трудно различить click и drag, потому что click также содержит mousedown & mouseup. Как я могу различить "щелчок мышью" и "перетаскивание" мышью тогда в Javascript?

Ответы [ 10 ]

177 голосов
/ 18 мая 2011

Я думаю, что разница в том, что * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 100 * * * * * * mousedown * mouseup *, но не клик.

.1007 *

32 голосов
/ 30 декабря 2013

Если вы уже используете 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);
  });
});
17 голосов
/ 24 сентября 2016

Это должно хорошо работать.Аналогичен принятому ответу (хотя и с использованием jQuery), но флаг isDragging сбрасывается только в том случае, если новая позиция мыши отличается от позиции на событии mousedown.В отличие от принятого ответа, это работает в последних версиях Chrome, где mousemove запускается независимо от того, была ли перемещена мышь.

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 = [];
    });

Вы также можете настроить проверку координат в mousemove, если выхочу добавить немного терпимости (то есть рассматривать крошечные движения как щелчки, а не перетаскивания).

12 голосов
/ 26 июня 2015

Как указывает mrjrdnthms в своем комментарии о принятом ответе, это больше не работает в Chrome (он всегда запускает движение мыши), я адаптировал ответ Густаво (поскольку я использую jQuery) для решения поведения Chrome. 1001 *

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

  });

});

Функция Array.prototype.equals происходит из этого ответа

11 голосов
/ 02 июля 2017

Если вы хотите использовать 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>

Это прямой клон того, что @ wong2 сделал в своем ответе, но преобразованный в RxJ.

Также интересное использование sample.Оператор sample возьмет последнее значение из источника (merge из mousedown и mousemove) и сгенерирует его, когда испустится внутренняя наблюдаемая (mouseup).

9 голосов
/ 26 июня 2018

Очиститель ES2015

let drag = false;

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

Не было никаких ошибок, как другие комментируют.

4 голосов
/ 26 мая 2017

Использование jQuery с 5-пиксельным x / y полем для определения сопротивления:

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");
});
3 голосов
/ 27 декабря 2016

Если просто отфильтровать случай перетаскивания, сделайте это так:

var moved = false;
$(selector)
  .mousedown(function() {moved = false;})
  .mousemove(function() {moved = true;})
  .mouseup(function(event) {
    if (!moved) {
        // clicked without moving mouse
    }
  });
1 голос
/ 11 апреля 2019

Pure JS с DeltaX и DeltaY

Это DeltaX и DeltaY в соответствии с комментарием в принятом ответе, чтобы избежать неприятных ощущений при попытке щелкнуть мышью и получить вместо этого операцию перетаскивания из-зана один ход мыши.

    deltaX = deltaY = 2;//px
    var element = document.getElementById('divID');
    element.addEventListener("mousedown", function(e){
        if (typeof InitPageX == 'undefined' && typeof InitPageY == 'undefined') {
            InitPageX = e.pageX;
            InitPageY = e.pageY;
        }

    }, false);
    element.addEventListener("mousemove", function(e){
        if (typeof InitPageX !== 'undefined' && typeof InitPageY !== 'undefined') {
            diffX = e.pageX - InitPageX;
            diffY = e.pageY - InitPageY;
            if (    (diffX > deltaX) || (diffX < -deltaX)
                    || 
                    (diffY > deltaY) || (diffY < -deltaY)   
                    ) {
                console.log("dragging");//dragging event or function goes here.
            }
            else {
                console.log("click");//click event or moving back in delta goes here.
            }
        }
    }, false);
    element.addEventListener("mouseup", function(){
        delete InitPageX;
        delete InitPageY;
    }, false);

   element.addEventListener("click", function(){
        console.log("click");
    }, false);
0 голосов
/ 27 июня 2019

Для публичного действия на карте OSM (поместите маркер на клик) вопрос был: 1) как определить длительность нажатия мыши вниз -> вверх (вы не можете себе представить создание нового маркера для каждого клика) и2) перемещалась ли мышь во время вниз -> вверх (т.е. пользователь перетаскивает карту).

const map = document.getElementById('map');

map.addEventListener("mousedown", position); 
map.addEventListener("mouseup", calculate);

let posX, posY, endX, endY, t1, t2, action;

function position(e) {

  posX = e.clientX;
  posY = e.clientY;
  t1 = Date.now();

}

function calculate(e) {

  endX = e.clientX;
  endY = e.clientY;
  t2 = (Date.now()-t1)/1000;
  action = 'inactive';

  if( t2 > 0.5 && t2 < 1.5) { // Fixing duration of mouse down->up

      if( Math.abs( posX-endX ) < 5 && Math.abs( posY-endY ) < 5 ) { // 5px error on mouse pos while clicking
         action = 'active';
         // --------> Do something
      }
  }
  console.log('Down = '+posX + ', ' + posY+'\nUp = '+endX + ', ' + endY+ '\nAction = '+ action);    

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...