[javascript] 마우스 “클릭”과 “끌기”를 구별하는 방법

내가 사용하는 jQuery.click한편, 내가 마우스 처리 할 필요가 라파엘 그래프에서 마우스 클릭 이벤트를 처리하는 drag이벤트를 마우스 드래그로 구성 mousedown, mouseupmousemove 라파엘있다.

구별하기 어려운 click하고 drag있기 때문에 click도 포함 mousedown& mouseup, 어떻게 자바 스크립트에서 다음 “드래그”& 마우스 “클릭”마우스를 구별 할 수 있습니까?



답변

차이점은 mousemove사이 mousedownmouseup 드래그 드래그 에 있지만 클릭에는 없다는 것입니다.

다음과 같이 할 수 있습니다 :

const element = document.createElement('div')
element.innerHTML = 'test'
document.body.appendChild(element)
let moved
let downListener = () => {
    moved = false
}
element.addEventListener('mousedown', downListener)
let moveListener = () => {
    moved = true
}
element.addEventListener('mousemove', moveListener)
let upListener = () => {
    if (moved) {
        console.log('moved')
    } else {
        console.log('not moved')
    }
}
element.addEventListener('mouseup', upListener)

// release memory
element.removeEventListener('mousedown', downListener)
element.removeEventListener('mousemove', moveListener)
element.removeEventListener('mouseup', upListener)


답변

이미 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);
  });
});


답변

클리너 ES2015

let drag = false;

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

다른 사람들이 언급했듯이 버그가 발생하지 않았습니다.


답변

이것은 잘 작동합니다. 허용 된 답변과 유사하지만 (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약간의 공차를 추가 하려면 좌표 체크인을 조정할 수도 있습니다 (예 : 작은 움직임은 드래그가 아닌 클릭으로 처리).


답변

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오퍼레이터는 소스로부터의 최신의 값을 (뜻 mergemousedownmousemove) 때 내부 관찰 (그것을 방출 mouseup) 방출한다.


답변

mrjrdnthms가 허용 된 답변에 대한 그의 의견에서 지적한 것처럼, 이것은 더 이상 Chrome에서 작동하지 않으며 (항상 마우스 이동을 발생시킵니다) Chrome 동작을 해결하기 위해 Gustavo의 답변을 조정했습니다 (jQuery를 사용하기 때문에).

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기능이에서 오는 대답


답변

이러한 모든 솔루션은 작은 마우스 움직임으로 인해 깨지거나 지나치게 복잡합니다.

다음은 두 개의 이벤트 리스너를 사용하는 간단한 적응 형 솔루션입니다. 델타는 코드가 클릭이 아닌 드래그로 코드를 분류하기 위해 위쪽 및 아래쪽 이벤트 사이에서 가로 또는 세로로 이동해야하는 거리 (픽셀 단위)입니다. 마우스 나 손가락을 들어 올리기 전에 몇 픽셀 움직일 때가 있기 때문입니다.

const delta = 6;
let startX;
let startY;

element.addEventListener('mousedown', function (event) {
  startX = event.pageX;
  startY = event.pageY;
});

element.addEventListener('mouseup', function (event) {
  const diffX = Math.abs(event.pageX - startX);
  const diffY = Math.abs(event.pageY - startY);

  if (diffX < delta && diffY < delta) {
    // Click!
  }
});