JS逻辑拖拽,3种方式

0 阅读3分钟

前言

  1. 拖拽应用的领域非常广泛,比如截图,画板,图片裁剪等等。
  2. 同时,这也是一些高端项目入门的基础,如低代码,数据可视化。
  3. 本次新开一个专题,主讲拖拽,当前是开篇,也是今后用到的基础。

示例

进入页面后,点击拖拽框架可以查看16点拖拽完美实现

支持拖拽旋转,限制出界,调整圆角,鼠标跟随旋转方向

mx2d.cn/

原理

先看现象,用户的鼠标移动,带着对应的元素跟着移动

可以把拖拽拆分成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)

这段代码会疯狂的绑定事件,移动的坐标就会发生异常

实现

注:各个版本都有自己的优劣,可以结合实际场景使用

实现也都基于上面提到的原理

事件组合版(个人推荐)

鼠标点下时,监听新的移动事件,鼠标抬起则释放事件

code.juejin.cn/pen/7612604…

事件分离版

需要额外引入一个变量来控制开启关闭状态

code.juejin.cn/pen/7612608…

API版

使用鼠标属性:movementXmovementY,两行代码搞定,非常省事,缺点是不是所有浏览器都支持,移动端也不支持,只能用在web端。

code.juejin.cn/pen/7612606…