前言
- 拖拽应用的领域非常广泛,比如截图,画板,图片裁剪等等。
- 同时,这也是一些高端项目入门的基础,如低代码,数据可视化。
- 本次新开一个专题,主讲拖拽,当前是开篇,也是今后用到的基础。
示例
进入页面后,点击拖拽框架可以查看16点拖拽完美实现
支持拖拽旋转,限制出界,调整圆角,鼠标跟随旋转方向
原理
先看现象,用户的鼠标移动,带着对应的元素跟着移动
可以把拖拽拆分成3步:开启,移动,结束;缺一不可。
开启
只有在鼠标点击对应的dom元素时,才需要拖拽功能,相当于启动了开关。如果没有这个开关,则所有图形都会跟着鼠标走,想必你也不希望看到这样的场景吧
移动
整个拖拽最核心的地方就在这里,理解不到位就要出问题。
EV录屏出来挨打,他的实现缺陷在于,遇到边界时,裁剪了越界的数值,导致回不去了
(通用)移动的思路是:
移动距离 =下一次鼠标移动的坐标-上一次鼠标移动的距离
最终坐标 =上一次移动的坐标 + 移动距离
接下来用代码实现思路
我们先只解决横向移动,纵向移动也就照葫芦画瓢了。
const box = document.getElementById('box')
const update = () => {
box.style.left = `${pos.x}px`
}
let pos = {
x: 0,
}
const onMousedown = () => {
//获取鼠标按下去的鼠标信息
const e1 = window.event
//闭包存储,用来解决上面提到的·上一次移动的坐标·
const initialPos = {
...pos,
}
const onMousemove = (e2) => {
// e1:它的坐标是不变的
// e2:鼠标移动的信息,实时更新的,e2-e1会形成正负移动的值
// 移动距离 = e2.x - e1.x
// initialPos.x :在按下dom时,会把pos的值缓存到initialPos中,所以记录了上一次移动的坐标
pos.x = initialPos.x + e2.x - e1.x
//结合上面提到的思路:最终坐标 = 上一次移动的坐标 + 下一次鼠标移动的坐标-上一次鼠标移动的距离
//更新dom节点
update()
}
const onMouseup = () => {
//移除事件监听,避免重复触发
document.removeEventListener('mousemove', onMousemove)
document.removeEventListener('mouseup', onMouseup)
}
document.addEventListener('mousemove', onMousemove)
document.addEventListener('mouseup', onMouseup)
}
结束
清场的作用,释放监听的事件,否则
document.addEventListener('mousemove', onMousemove)
这段代码会疯狂的绑定事件,移动的坐标就会发生异常
实现
注:各个版本都有自己的优劣,可以结合实际场景使用
实现也都基于上面提到的原理
事件组合版(个人推荐)
鼠标点下时,监听新的移动事件,鼠标抬起则释放事件
事件分离版
需要额外引入一个变量来控制开启或关闭状态
API版
使用鼠标属性:movementX,movementY,两行代码搞定,非常省事,缺点是不是所有浏览器都支持,移动端也不支持,只能用在web端。