「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
在业务中遇到了点击事件与拖拽事件冲突的问题,具体的内容是在3D场景中需要拖动模型放置进一个柜子里,而本身点击柜子会通过点击事件执行部分逻辑,所以在将模型拖动到柜子里之后会触发相应的点击事件。
| 事件类型 | 说明 |
|---|---|
| click | 单击鼠标左键时触发 |
| mousedown | 单击任意一个鼠标按钮时触发 |
| mouseup | 松开任意一个鼠标按钮时触发 |
| mousemove | 鼠标移动时触发 |
问题就出在这三个事件的联系上 -> click = mousedown + mouseup
document.onmousedown = function(event){ // 按下鼠标时,初始化处理
console.log('onmousedown');
}
document.onmouseup = function(event){ // 松开鼠标
console.log('onmouseup');
}
document.onclick = function(event) { // 单击
console.log('click');
}
document.onmousemove = function(event){ // 移动
console.log('onmousemove');
}
// 单次点击鼠标会依次打印
// onmousedown
// onmouseup
// click
// 模拟拖动操作会依次打印
// onmousedown
// onmousemove
// onmouseup
// click
经过测试click事件是最后触发的,所以解决的思路是做一个开关,通过开关去控制click中的事件是否执行,而dragControls相应的事件(dragstart/drag/dragend)效果与鼠标事件类似,并且在当前业务中dragControls控件中需要实现的逻辑与click事件中的逻辑是没有必然联系的。
所以我直接在dragControls控件的drag事件中操作开关(switchFlag),然后通过对click事件进行相应的改造,具体的实现如下:
// switchFlag变量作为开关
let switchFlag = false
// dragControls相关代码
dragControls.addEventListener("dragstart", function(event) {
controls.enabled = false;
});
dragControls.addEventListener("drag", function(event) {
switchFlag = true
});
dragControls.addEventListener("dragend", function(event) {
controls.enabled = true;
});
// 改造点击事件
function onMouseClick(event) {
if (switchFlag) {
switchFlag = false
return false
} else {
// do someting
}
}
window.addEventListener("click", onMouseClick);
上述的代码脱离dragControls的话内容基本不变,如下:
// switchFlag变量作为开关
let switchFlag = false
document.onmousedown = function(event){ // 按下鼠标时,初始化处理
console.log('onmousedown');
}
document.onmouseup = function(event){ // 松开鼠标
console.log('onmouseup');
}
document.onclick = function(event) { // 单击
if (swickFlag) {
swickFlag = true
return false
} else {
console.log('click');
}
}
document.onmousemove = function(event){ // 移动
console.log('onmousemove');
switchFlag = ture
}
现在我们已经实现了拖动后不触发点击事件,但是仔细想想上述的逻辑有些过于生硬。
假设使用上述的代码,那么当鼠标点下的时候鼠标不能发生任何偏移,也就是不能触发mousemove事件,否则点击事件就无法生效,这个时候判断逻辑就需要对偏移量有一定的容忍度,需要在mousedown时记录当前的鼠标位置,与mouseup事件触发时的鼠标位置进行比较,以此为基准再对开关(swickFlag)进行操作。