拖拽组件需求
在开发过程中遇到的需求:要求拖拽改变元素的大小和位置,主要是用于可视化大屏的创建,考虑到项目的二次开发以及后续,作者决定自己开发一个拖拽组件,供项目使用。(此组件是vue3版本,如果需要vue2版本文章底部也有连接)
组件名称:gaius-utils,github地址
拖拽位置部分(只提供了主要的逻辑)
这部分主要是通过监听mousedown、mousemove、mouseup事件,获取鼠标按下及鼠标弹起的事件信息来获取鼠标移动的距离,根据下图的示意图可知:鼠标移动的距离和dom元素要移动的距离是相同的,接下来只需要获得到鼠标的移动的距离然后和dom初始位置在X、Y轴上进行加减计算便可以得到dom的新位置坐标。
公式说明
鼠标按下后 鼠标相当于当前dom的位置应该是不变的(dom随着鼠标移动),所以disX,disY的值就是固定的,mousemove移动过程中的鼠标位置在变更,dom位置X,Y应该也是随之变化。他们之前总是差着disX、disY的距离即可。
当鼠标弹起时注销事件即可。
代码部分如下
let { left: curX, top: curY } = transformToValue() //通过函数获取当前dom的X\Y的位置
let disX = e.clientX - parseFloat(curX) // 鼠标按下时的位置和dom之前X轴的差距
let disY = e.clientY - parseFloat(curY)// 鼠标按下时的位置和dom之间Y轴的差距
document.onmousemove = function (e) {
let x = e.clientX - disX // 鼠标移动后的位置 - X差距 就是现在domX的位置
let y = e.clientY - disY //鼠标移动后的位置 - Y差距 就是现在domY的位置
dragResize.value.style.transform = `translate3d(${x}px, ${y}px,0)`
}
document.onmouseup = function () {
document.onmousemove = null
document.onmouseup = null
}
(完整代码可以在上面的github地址查阅)
拖拽改变大小部分
同上述,鼠标移动的距离即是dom变更前后的宽高的差值。不多说上代码。
const height = dragResize.value.clientHeight
const width = dragResize.value.clientWidth
const startX = event.clientX
const startY = event.clientY
const move = (moveEvent:MouseEvent) => {
const currX = moveEvent.clientX
const currY = moveEvent.clientY
const disY = currY - startY
const disX = currX - startX
const newHeight = (height + disY) > minh.value
? (height + disY)
: minh.value
const newWidth = (width + disX) > minw.value
? (width + disX)
: minw.value
dragResize.value.style.width = newWidth + 'px'
dragResize.value.style.height = newHeight + 'px'
}
const up = () => {
document.removeEventListener('mousemove', move)
document.removeEventListener('mouseup', up)
}
除此之外也有以下几点需要考虑
直接修改dom的left、top会引发重排消耗的性能相较于重绘大,所以最后采用translate只重绘又因为translate3d 会使用显卡计算减少卡顿效果,本组件中使用的是translate3d。
本组件在实际代码中考虑到这一点会通过比较父级dom的大小以及计算位置关系保证不会超出父组件。
在开发过程中同时开发了vue2的版本不过较长时间未更新。
组件名称(ray-drag-resize-v2)npm地址,github地址