我使用jQuery。点击来处理Raphael图形上的鼠标点击事件,同时,我需要处理鼠标拖动事件,鼠标拖动在Raphael中由鼠标下拉,鼠标上拉和鼠标移动组成。

很难区分点击和拖动,因为点击也包含鼠标下拉和鼠标上拉,我怎么能区分鼠标“点击”和鼠标“拖动”然后在Javascript?


当前回答

如果你已经在使用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);
  });
});

其他回答

我认为区别在于,在拖拽中,mousedown和mouseup之间有一个鼠标移动,但在点击中没有。

你可以这样做:

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)

你可以这样做:

var div = document.getElementById("div"); div.addEventListener("mousedown", function() { window.addEventListener("mousemove", drag); window.addEventListener("mouseup", lift); var didDrag = false; function drag() { //when the person drags their mouse while holding the mouse button down didDrag = true; div.innerHTML = "drag" } function lift() { //when the person lifts mouse if (!didDrag) { //if the person didn't drag div.innerHTML = "click"; } else div.innerHTML = "drag"; //delete event listeners so that it doesn't keep saying drag window.removeEventListener("mousemove", drag) window.removeEventListener("mouseup", this) } }) body { outline: none; box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; overflow: hidden; } #div { /* calculating -5px for each side of border in case border-box doesn't work */ width: calc(100vw - 10px); height: calc(100vh - 10px); border: 5px solid orange; background-color: yellow; font-weight: 700; display: grid; place-items: center; user-select: none; cursor: pointer; padding: 0; margin: 0; } <html> <body> <div id="div">Click me or drag me.</div> </body> </html>

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

}

另一个基于类的香草JS使用距离阈值的解决方案

private initDetectDrag(element) {
    let clickOrigin = { x: 0, y: 0 };
    const dragDistanceThreshhold = 20;

    element.addEventListener('mousedown', (event) => {
        this.isDragged = false
        clickOrigin = { x: event.clientX, y: event.clientY };
    });
    element.addEventListener('mousemove', (event) => {
        if (Math.sqrt(Math.pow(clickOrigin.y - event.clientY, 2) + Math.pow(clickOrigin.x - event.clientX, 2)) > dragDistanceThreshhold) {
            this.isDragged = true
        }
    });
}

在类内部添加(SOMESLIDER_ELEMENT也可以是document为global):

private isDragged: boolean;
constructor() {
    this.initDetectDrag(SOMESLIDER_ELEMENT);
    this.doSomeSlideStuff(SOMESLIDER_ELEMENT);
    element.addEventListener('click', (event) => {
        if (!this.sliderIsDragged) {
            console.log('was clicked');
        } else {
            console.log('was dragged, ignore click or handle this');
        }
    }, false);
}

所有这些解决方案要么在微小的鼠标移动上失效,要么过于复杂。

下面是一个使用两个事件侦听器的简单适应性解决方案。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!
  }
});