-
Notifications
You must be signed in to change notification settings - Fork 2
/
draggable.js
72 lines (56 loc) · 1.8 KB
/
draggable.js
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
export function makeDraggable(element, onDrag, onStart, onEnd, threshold = 3) {
if (!element) return () => void 0
let unsubscribeDocument = () => void 0
const onPointerDown = (event) => {
if (event.currentTarget !== event.target) return
if (event.button !== 0) return
event.preventDefault()
event.stopPropagation()
let startX = event.clientX
let startY = event.clientY
let isDragging = false
const onPointerMove = (event) => {
event.preventDefault()
event.stopPropagation()
const x = event.clientX
const y = event.clientY
const dx = x - startX
const dy = y - startY
if (isDragging || Math.abs(dx) > threshold || Math.abs(dy) > threshold) {
const rect = element.getBoundingClientRect()
const { left, top } = rect
if (!isDragging) {
onStart?.(startX - left, startY - top)
isDragging = true
}
onDrag(dx, dy, x - left, y - top)
startX = x
startY = y
}
}
const onPointerUp = () => {
if (isDragging) {
onEnd?.()
}
unsubscribeDocument()
}
const onTouchMove = (event) => {
if (isDragging) {
event.preventDefault()
}
}
document.addEventListener('pointermove', onPointerMove)
document.addEventListener('pointerup', onPointerUp)
document.addEventListener('touchmove', onTouchMove, { passive: false })
unsubscribeDocument = () => {
document.removeEventListener('pointermove', onPointerMove)
document.removeEventListener('pointerup', onPointerUp)
document.removeEventListener('touchmove', onTouchMove)
}
}
element.addEventListener('pointerdown', onPointerDown)
return () => {
unsubscribeDocument()
element.removeEventListener('pointerdown', onPointerDown)
}
}