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

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


当前回答

基于这个答案,我在React组件中这样做:

export default React.memo(() => {
    const containerRef = React.useRef(null);

    React.useEffect(() => {
        document.addEventListener('mousedown', handleMouseMove);

        return () => document.removeEventListener('mousedown', handleMouseMove);
    }, []);

    const handleMouseMove = React.useCallback(() => {
        const drag = (e) => {
            console.log('mouse is moving');
        };

        const lift = (e) => {
            console.log('mouse move ended');
            window.removeEventListener('mousemove', drag);
            window.removeEventListener('mouseup', this);
        };

        window.addEventListener('mousemove', drag);
        window.addEventListener('mouseup', lift);
    }, []);

    return (
        <div style={{ width: '100vw', height: '100vh' }} ref={containerRef} />
    );
})

其他回答

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

如果只是为了过滤掉拖动的情况,这样做:

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

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

}

基于这个答案,我在React组件中这样做:

export default React.memo(() => {
    const containerRef = React.useRef(null);

    React.useEffect(() => {
        document.addEventListener('mousedown', handleMouseMove);

        return () => document.removeEventListener('mousedown', handleMouseMove);
    }, []);

    const handleMouseMove = React.useCallback(() => {
        const drag = (e) => {
            console.log('mouse is moving');
        };

        const lift = (e) => {
            console.log('mouse move ended');
            window.removeEventListener('mousemove', drag);
            window.removeEventListener('mouseup', this);
        };

        window.addEventListener('mousemove', drag);
        window.addEventListener('mouseup', lift);
    }, []);

    return (
        <div style={{ width: '100vw', height: '100vh' }} ref={containerRef} />
    );
})

有同样的问题,最近在一个树列表中,用户可以点击项目或拖动它,使这个小指针类,并把它放在我的utils.js

function Pointer(threshold = 10) {
  let x = 0;
  let y = 0;

  return {
    start(e) {
     x = e.clientX;
     y = e.clientY;
    },

    isClick(e) {
      const deltaX = Math.abs(e.clientX - x);
      const deltaY = Math.abs(e.clientY - y);
      return deltaX < threshold && deltaY < threshold;
    }
  }
}

下面你可以看到它的工作原理:

function Pointer(threshold = 10) { let x = 0; let y = 0; return { start(e) { x = e.clientX; y = e.clientY; }, isClick(e) { const deltaX = Math.abs(e.clientX - x); const deltaY = Math.abs(e.clientY - y); return deltaX < threshold && deltaY < threshold; } } } const pointer = new Pointer(); window.addEventListener('mousedown', (e) => pointer.start(e)) //window.addEventListener('mousemove', (e) => pointer.last(e)) window.addEventListener('mouseup', (e) => { const operation = pointer.isClick(e) ? "Click" : "Drag" console.log(operation) })