IT

마우스 "클릭"과 "끌기"를 구별하는 방법

lottoking 2020. 6. 15. 08:05
반응형

마우스 "클릭"과 "끌기"를 구별하는 방법


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

구별하기 어려운 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);
  });
});

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


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


클리너 ES2015

let drag = false;

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

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


If you feel like using 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>

This is a direct clone of what @wong2 did in his answer, but converted to RxJs.

Also interesting use of sample. The sample operator will take the latest value from the source (the merge of mousedown and mousemove) and emit it when the inner observable (mouseup) emits.


Using jQuery with a 5 pixel x/y theshold to detect the drag:

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

If just to filter out the drag case, do it like this:

var moved = false;
$(selector)
  .mousedown(function() {moved = false;})
  .mousemove(function() {moved = true;})
  .mouseup(function(event) {
    if (!moved) {
        // clicked without moving mouse
    }
  });

Pure JS with DeltaX and DeltaY

This DeltaX and DeltaY as suggested by a comment in the accepted answer to avoid the frustrating experience when trying to click and get a drag operation instead due to a one tick mousemove.

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

For a public action on an OSM map (position a marker on click) the question was: 1) how to determine the duration of mouse down->up (you can't imagine creating a new marker for each click) and 2) did the mouse move during down->up (i.e user is dragging the map).

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

}

참고URL : https://stackoverflow.com/questions/6042202/how-to-distinguish-mouse-click-and-drag

반응형