three 解决dragControls与点击事件冲突的办法

1,524 阅读2分钟

「这是我参与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)进行操作。