我使用jQuery。点击来处理Raphael图形上的鼠标点击事件,同时,我需要处理鼠标拖动事件,鼠标拖动在Raphael中由鼠标下拉,鼠标上拉和鼠标移动组成。
很难区分点击和拖动,因为点击也包含鼠标下拉和鼠标上拉,我怎么能区分鼠标“点击”和鼠标“拖动”然后在Javascript?
我使用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);
});
});
这应该能很好地工作。类似于已接受的答案(虽然使用jQuery),但只有当新的鼠标位置与mousedown事件上的位置不同时,isdrag标志才会重置。与公认的答案不同,这适用于最新版本的Chrome,无论鼠标是否移动,鼠标移动都会被触发。
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 = [];
});
你也可以在鼠标移动中调整坐标检查,如果你想增加一点公差(即将微小的移动视为点击,而不是拖动)。
下面的编码是检测鼠标的移动。
它适用于大多数情况。这也取决于 关于如何将mouseevent处理为单击。 在JavaScript中,检测非常简单。它不关心如何 在鼠标下拉和鼠标上拉之间按住或移动。 Event.detail不会重置为1当你的鼠标移动 鼠标下拉和鼠标上拉。 如果你需要区分点击和长按,你需要 检查事件的差异。时间戳。
// ==== add the code at the begining of your coding ==== let clickStatus = 0; (() => { let screenX, screenY; document.addEventListener('mousedown', (event) => ({screenX, screenY} = event), true); document.addEventListener('mouseup', (event) => (clickStatus = Math.abs(event.screenX - screenX) + Math.abs(event.screenY - screenY) < 3), true); })(); // ==== add the code at the begining of your coding ==== $("#draggable").click(function(event) { if (clickStatus) { console.log(`click event is valid, click count: ${event.detail}`) } else { console.log(`click event is invalid`) } }) <!doctype html> <html lang="en"> <!-- coding example from https://jqueryui.com/draggable/ --> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>jQuery UI Draggable - Default functionality</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <link rel="stylesheet" href="/resources/demos/style.css"> <style> #draggable { width: 150px; height: 150px; padding: 0.5em; } </style> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script> $( function() { $( "#draggable" ).draggable(); } ); </script> </head> <body> <div id="draggable" class="ui-widget-content"> <p>Drag me around</p> </div> </body> </html>
所有这些解决方案要么在微小的鼠标移动上失效,要么过于复杂。
下面是一个使用两个事件侦听器的简单适应性解决方案。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!
}
});
来自@Przemek的回答,
函数listenClickOnly(元素,回调,阈值=10){ 让拖动= 0; 元素。addEventListener('mousedown', () => drag = 0); 元素。addEventListener('mousemove', () => drag++); 元素。addEventListener('mouseup', e => { 如果(拖动<阈值)回调(e); }); } listenClickOnly ( 文档, () => console.log('click'), 10 );