easy-drag——轻松帮你实现丝滑的拖拽效果

9,541 阅读2分钟

作为一名前端打工人,你大概率遇到过这样的需求:实现一个可拖拽的小组件,比如掘金页面右下角的反馈图标。

image.png

可拖拽小组件要怎么做?easy-drag 就是为解决这个问题诞生的!

原理

首先,我们要确定怎样实现偏移效果,这里无非就两种:

  • 一种是利用绝对定位,拖拽时调整topleft值,但是这种方案依赖父组件的定位方式
  • 另一种是利用transform,拖拽时调整元素的偏移向量,这种方案不依赖父组件的定位方式

这里我们当然要选择后者,因为后者可以适应更多的场景。

然后,我们要确定怎么计算偏移向量,这里我们监听mouse事件来实现:

  1. 监听元素的mousedown事件,记录元素初始偏移位置;
  2. 监听文档的mousemove事件,根据鼠标位移向量修改元素的偏移位置;
  3. 监听文档的mouseup事件,重置数据。

这样我们就确定了大致方案。

实现

大致方案确定了,具体的实现就是细枝末节了,但是需要注意的点还是不少的:

元素原先有 transform 属性怎么办?

因为元素原先是可以设置transform属性的,所以我们设置的transform属性必须要在元素样式的transform基础上叠加,所以需要用到 window.getComputedStyle(element).transform,然后拼接transform属性

元素怎么跑偏了?

QQ20211015-160522-HD.gif

原因是拼接transform属性时将拖拽的translate3d拼接到了原有的transform值后面,而原有的ratate会将元素的坐标系旋转,导致再施加平移效果时就会“跑偏”。

将平移效果加到原有transform值前面就可以避免这个问题。

性能怎么样?

QQ20211015-161436-HD.gif

是不是如丝般顺滑,因为translate3d属性会使浏览器为元素单独生成图层,而通过translate3d修改元素的位置时只会触发浏览器的重新合成图层,并不会触发重排重绘,所以自然非常顺滑~

使用方式

安装

npm i easy-drag

使用

import enableDrag from 'easy-drag';
const disableDrag = enableDrag(document.querySelector('.draggable'));
disableDrag();

功能

  • easy-drag 支持取消拖拽
  • easy-drag 支持设置拖拽范围,默认不可超出document.body
  • easy-drag 支持设置拖拽点,适用场景:弹窗需要设置为可拖拽的,但只能拖拽标题区域
  • easy-drag 支持设置自定义回调,包含onDragStartonDragonDragEnd

Github

easy-drag: github.com/junqiuzhang…

同时安利一下本人的其他Github项目: