需求:
1. 一定是由三个事件组成
1-1. 鼠标移动, 随着光标移动, 盒子实时跟着光标走
1-2. 鼠标按下, 按下以后, 盒子可以跟着走
1-3. 鼠标抬起, 抬起以后, 盒子不在跟着走
+ 核心问题: 如何能让盒子跟着走, 就是需要 mousemove 的事件处理函数能执行
=> 准备一个开关, 在 mousemove 事件处理函数内
=> 直接判断开关如果是 false, 直接 return, 否则在执行
+ 问题1: 什么时候需要 mousemove 内的代码正常执行
=> 按下以后, 可以在鼠标按下事件内把 开关赋值为 true
+ 问题2: 什么时候 mousemove 不能在正常执行
=> 抬起以后, 可以在鼠标抬起事件内把 开关赋值给 false
2. 在移动事件内, 让 div 跟着走就可以了
+ 问题3: 真的要把事件绑定在 div 身上吗 ?
=> 假设你把事件绑定在 div 身上, 当你给 div 赋值的时候
=> 你光标的坐标点赋值 给 div , 表示 div 的左上角和你的光标是重叠了
=> 当你向右下方移动的时候, 你的光标依旧是在 div 身上
=> 只要你向左上移动, 哪怕只动一点点, 都是离开了 div
=> 因为事件是绑定给 div 的, 所以只能在 div 身上移动的时候触发
=> 解决(暂时): 把光标让在 div 的中间
=> 解决(永久): 把事件向上绑定, document
+ 问题4: 拿到哪一组坐标 ?
=> 整屏移动, 最好使用 client 一组
吸附
+ 给拖拽的元素加上一个边界值判断
+ 边界值只能在可视窗口内
+ 问题1: 在什么位置进行判断 ?
=> 在拿到坐标和赋值之间进行边界值判断
+ 如何判断左边和上边边界 ?
=> 左边和上边的最小值一定是 0, 不能再小了
+ 如何判断右边的边界 ?
=> 移动最大距离就是 可视窗口的 宽度 - 盒子的宽度
* {
margin: 0;
padding: 0;
}
div {
width: 200px;
height: 200px;
background-color: pink;
position: absolute;
}
<div></div>
// 获取元素
let div = document.querySelector('div')
// 提前准备一个变量当做开关
let flag = false
// 鼠标按下
div.onmousedown = () => {
// 打开开关
flag = true
}
// 鼠标抬起
div.onmouseup = () => {
flag = false
}
// 鼠标移动
document.onmousemove = e => {
// 开关判断
if (flag === false) return
// 处理事件对象兼容
e = e || window.event
let x = e.clientX - 100
let y = e.clientY - 100
// 边界值判断
// 左边
if (x <= 50) x = 0
// 上边
if (y <= 50) y = 0
// 右边
if (x >= document.documentElement.clientWidth - div.offsetWidth - 50) {
x = document.documentElement.clientWidth - div.offsetWidth
}
// 下边
if (y >= document.documentElement.clientHeight - div.offsetHeight - 50) {
y = document.documentElement.clientHeight - div.offsetHeight
}
// 赋值给 div
div.style.left = x + 'px'
div.style.top = y + 'px'
}