解决方案:添加mouseleave,只要拖拽脱离了dom元素区域就停止
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
width: 80px;
height: 80px;
background-color: pink;
border-radius: 50%;
text-align: center;
line-height: 80px;
color: red;
cursor: pointer;
user-select: none;
}
</style>
</head>
<body>
<nav style="padding:20px 40px;">
<div>drag</div>
</nav>
<script>
const dragDom = document.querySelector("div");
//鼠标按下时的pageX,pageY
let startPoint = {};
//dom相对于最初位置的总共移动距离
let moveDistance = { x: 0, y: 0 };
//标志鼠标是否在当前dom按下,避免没有按下鼠标也触发mousemove事件的问题出现
dragDom.isTouching = false;
dragDom.addEventListener("mousedown", function (e) {
dragDom.isTouching = true;
//记录按下鼠标的位置
startPoint.x = e.pageX;
startPoint.y = e.pageY;
}, false)
dragDom.addEventListener("mousemove", function (e) {
//如果没有按下鼠标,就不用执行后边的代码
if(!this.isTouching) return;
let diff = {};
//移动后的位置减去按下鼠标的位置就是需要移动的距离
diff.x = e.pageX - startPoint.x;
diff.y = e.pageY - startPoint.y;
//之所以+moveDistanc.x是因为这次的移动是上次移动的位置点进行累加的
move(dragDom, { x: diff.x + moveDistance.x, y: diff.y + moveDistance.y })
}, false)
function move(el, { x = 0, y = 0 }) {
el.style.transform = `translate3d(${x}px,${y}px,0)`;
}
dragDom.addEventListener("mouseup", function (e) {
if(!this.isTouching) return
//鼠标抬起时,记录 总的移动距离 += 本次移动的距离
moveDistance.x += e.pageX - startPoint.x;
moveDistance.y += e.pageY - startPoint.y;
dragDom.isTouching = false;
}, false)
//mousemove移动太快,脱离了dom区域之后再松开鼠标并不会触发mouseup事件,所以再添加一个mouseleave事件解决这个问题
dragDom.addEventListener("mouseleave",function(e) {
if(!this.isTouching) return
moveDistance.x += e.pageX - startPoint.x;
moveDistance.y += e.pageY - startPoint.y;
dragDom.isTouching = false;
},false)
</script>
</body>
</html>