我使用jQuery。点击来处理Raphael图形上的鼠标点击事件,同时,我需要处理鼠标拖动事件,鼠标拖动在Raphael中由鼠标下拉,鼠标上拉和鼠标移动组成。
很难区分点击和拖动,因为点击也包含鼠标下拉和鼠标上拉,我怎么能区分鼠标“点击”和鼠标“拖动”然后在Javascript?
我使用jQuery。点击来处理Raphael图形上的鼠标点击事件,同时,我需要处理鼠标拖动事件,鼠标拖动在Raphael中由鼠标下拉,鼠标上拉和鼠标移动组成。
很难区分点击和拖动,因为点击也包含鼠标下拉和鼠标上拉,我怎么能区分鼠标“点击”和鼠标“拖动”然后在Javascript?
当前回答
我认为区别在于,在拖拽中,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)
其他回答
纯JS与DeltaX和delay
这个DeltaX和delay是由接受的答案中的评论所建议的,以避免由于鼠标移动一划而试图单击并获得拖动操作时的令人沮丧的体验。
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);
有同样的问题,最近在一个树列表中,用户可以点击项目或拖动它,使这个小指针类,并把它放在我的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) })
清洁ES2015
Let drag = false; 文档。addEventListener('mousedown', () => drag = false); 文档。addEventListener('mousemove', () => drag = true); 文档。addEventListener('mouseup', () => console.log(拖动?'拖动':'点击'));
正如其他人评论的那样,没有遇到任何bug。
如果你想使用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>
这是@wong2在他的回答中所做的直接克隆,但转换为RxJs。
样本的使用也很有趣。示例操作符将从源(mousedown和mousemove的合并)中获取最新的值,并在内部观察对象(mouseup)发出时发出它。
基于这个答案,我在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} />
);
})