使用鼠标事件实现拖拽

相关的知识点

  1. clientX,offsetX,pageX,screenX的区别:参考
  2. 鼠标事件:mousedown、mousemove、mouseup
  3. 使用translate改变元素位置比使用top/left的性能高:参考1参考2

原理

  1. 点击拖拽元素时:记录鼠标的位置(X, Y)
  2. 拖拽元素时:
    • 获取鼠标当前位置(currentX, currentY)
    • 计算出移动距离(translateX = currentX - X, translateY = currentY - Y)
    • 修改元素的样式(transform: translate(translateX, translateY))
  3. 鼠标释放后,停止拖拽元素:重设元素样式(top, left, transform)

实现

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 当鼠标点击dragElement时,就会可以拖动target
* @return - 返回一个dragEvent对象,该对象有remove方法,用于移除事件
*/
function addDragEvent (drag, target) {
const params = {
flag: false, // 标识拖拽元素是否被选择
clientX: 0, // 记录起始位置
clientY: 0,
translateX: 0, // 记录移动距离
translateY: 0
}
const mousedown = dom.addListener(drag, 'mousedown', (event) => {
params.clientX = parseInt(event.clientX)
params.clientY = parseInt(event.clientY)
params.flag = true
})
const mousemove = dom.addListener(window, 'mousemove', (event) => {
if (params.flag) {
const {clientX, clientY} = event
params.translateX = parseInt(clientX) - params.clientX
params.translateY = parseInt(clientY) - params.clientY
target.style.transform = `translate(${params.translateX}px, ${params.translateY}px)`
}
})
const mouseup = dom.addListener(window, 'mouseup', (event) => {
if (params.flag) {
params.flag = false
const {clientX, clientY} = event
target.style.transform = `translate(0px, 0px)`
//
target.style.top = `${parseInt(target.style.top || 0) + params.translateY}px`
target.style.left = `${parseInt(target.style.left || 0) + params.translateX}px`
params.translateX = 0
params.translateY = 0
}
})
return {
remove: () => {
mousedown.remove()
mousemove.remove()
mouseup.remove()
}
}
}