作为一名前端打工人,你大概率遇到过这样的需求:实现一个可拖拽的小组件,比如掘金页面右下角的反馈图标。
可拖拽小组件要怎么做?easy-drag 就是为解决这个问题诞生的!
原理
首先,我们要确定怎样实现偏移效果,这里无非就两种:
- 一种是利用绝对定位,拖拽时调整
top和left值,但是这种方案依赖父组件的定位方式 - 另一种是利用
transform,拖拽时调整元素的偏移向量,这种方案不依赖父组件的定位方式
这里我们当然要选择后者,因为后者可以适应更多的场景。
然后,我们要确定怎么计算偏移向量,这里我们监听mouse事件来实现:
- 监听元素的
mousedown事件,记录元素初始偏移位置; - 监听文档的
mousemove事件,根据鼠标位移向量修改元素的偏移位置; - 监听文档的
mouseup事件,重置数据。
这样我们就确定了大致方案。
实现
大致方案确定了,具体的实现就是细枝末节了,但是需要注意的点还是不少的:
元素原先有 transform 属性怎么办?
因为元素原先是可以设置transform属性的,所以我们设置的transform属性必须要在元素样式的transform基础上叠加,所以需要用到
window.getComputedStyle(element).transform,然后拼接transform属性
元素怎么跑偏了?
原因是拼接transform属性时将拖拽的translate3d拼接到了原有的transform值后面,而原有的ratate会将元素的坐标系旋转,导致再施加平移效果时就会“跑偏”。
将平移效果加到原有transform值前面就可以避免这个问题。
性能怎么样?
是不是如丝般顺滑,因为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 支持设置自定义回调,包含
onDragStart、onDrag、onDragEnd
Github
easy-drag: github.com/junqiuzhang…
同时安利一下本人的其他Github项目:
- web版Minecraft:github.com/junqiuzhang…
- wegl粒子爆炸效果:github.com/junqiuzhang…
- react虚拟化渲染:github.com/junqiuzhang…