如何区分鼠标“点击”和“拖动”

IT技术 javascript dom-events
2021-01-19 11:52:46

jQuery.click用来处理 Raphael 图上的鼠标点击事件,同时,我需要处理鼠标drag事件,鼠标拖动由mousedown,mouseupmousemoveRaphael 组成。

很难区分clickdrag因为click也包含mousedown& mouseup,如何在Javascript中区分鼠标“单击”和鼠标“拖动”?

6个回答

我认为不同之处在于拖动中有一个mousemovebetweenmousedownmouseupin ,而不是 click 。

你可以这样做:

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)

我正在运行 Chrome 56.0.2924.87(64 位),但我没有遇到 @mrjrdnthms 所描述的问题。
2021-03-15 11:52:46
只要记住在 mousemove 上要求最小增量 X 或 Y 来触发拖动。由于一个勾号鼠标移动,尝试单击并获得拖动操作会令人沮丧
2021-03-23 11:52:46
@AmerllicA 这可能不是错误而是预期的行为,但是如果这对您的用例感兴趣,您可以观看 mouseenter 和 mouseleave 事件
2021-04-04 11:52:46
此接受的答案代码应包括 XY 鼠标坐标之间的最小增量条件,mousedownmouseup不是侦听mousemove事件以设置标志。此外,它将解决@mrjrdnthms 提到的问题
2021-04-08 11:52:46
我认为这在最新的 chrome 中不再适用: 32.0.1700.72 Mousemove 无论您是否移动鼠标都会触发
2021-04-11 11:52:46

清洁工 ES2015

let drag = false;

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

没有遇到任何错误,正如其他人评论的那样。

@AmirKeibi 你可以计算鼠标移动的次数(或者甚至计算两次点击之间的距离,但这会矫枉过正)
2021-03-22 11:52:46
这会受到轻微移动的点击的影响。
2021-04-05 11:52:46

如果您已经在使用 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);
  });
});
有时当我点击一个元素时,“evt.type”返回“mousemove”而不是mouseup。我该如何解决这个问题?
2021-03-21 11:52:46
@ChiMo我正在一直使用从第一存储鼠标位置evt和与第二位置进行比较evt,所以,例如:if (evt.type === 'mouseup' || Math.abs(evt1.pageX - evt2.pageX) < 5 || Math.abs(evt1.pageY - evt2.pageY) < 5) { ...
2021-03-24 11:52:46
我尝试了这个问题的所有其他答案,这是唯一一个在检查 时有效的答案,.on('mouseup mousemove touchend touchmove')最重要的是没有设置位置变量。很棒的解决方案!
2021-03-25 11:52:46
即使您在单击时稍微移动鼠标,也会显示drag这里可能需要像其他评论所说的额外范围。
2021-04-08 11:52:46

所有这些解决方案要么因微小的鼠标移动而中断,要么过于复杂。

这是一个使用两个事件侦听器的简单适应性解决方案。Delta 是以像素为单位的距离,您必须在向上和向下事件之间水平或垂直移动代码才能将其归类为拖动而不是点击。这是因为有时您会在抬起鼠标或手指之前将其移动几个像素。

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!
  }
});
我用解释更新了答案。基本上如果你的手指小于 6 像素,它仍然会被算作一次点击。如果它移动了 6 个或更多像素,它将被视为拖动。
2021-03-24 11:52:46
迄今为止最好的答案!
2021-03-26 11:52:46
好的。请注意,这在某些情况下无法正常工作一个例子:拖放。将某些东西拖走但又回来了,因为用户改变了主意,结果可能会产生不希望的点击。在这种情况下,必须检查阈值增量,mousemove正如这里的一些答案所建议的那样。
2021-04-01 11:52:46
@Haziq 我认为正如人们在顶级解决方案的评论中提到的那样delta,“由于鼠标移动一个勾,尝试单击并获得拖动操作会令人沮丧”
2021-04-04 11:52:46
嗨@andreyrd,我可以知道这delta是用来做什么的吗?这与移动设备中的点击有关吗?
2021-04-06 11:52:46

这应该很好用。类似于已接受的答案(尽管使用 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如果您想增加一点容差(即将微小的移动视为点击,而不是拖动),您也可以调整坐标检入