Skip to content

Commit

Permalink
Fix: draggable on mobile (katspaugh#3356)
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh authored Nov 26, 2023
1 parent 1bd9bc2 commit 2509d07
Showing 1 changed file with 43 additions and 47 deletions.
90 changes: 43 additions & 47 deletions src/draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,80 +5,76 @@ export function makeDraggable(
onEnd?: () => void,
threshold = 5,
): () => void {
let unsub = () => {
return
}

if (!element) return unsub
if (!element) return () => void 0

const down = (e: PointerEvent) => {
// Ignore the right mouse button
if (e.button === 2) return
let unsubscribeDocument = () => void 0

e.preventDefault()
e.stopPropagation()
element.style.touchAction = 'none'
const onPointerDown = (event: PointerEvent) => {
if (event.button !== 0) return

let startX = e.clientX
let startY = e.clientY
let startX = event.clientX
let startY = event.clientY
let isDragging = false

const move = (e: PointerEvent) => {
e.preventDefault()
e.stopPropagation()

const x = e.clientX
const y = e.clientY
const onPointerMove = (event: PointerEvent) => {
const x = event.clientX
const y = event.clientY
const dx = x - startX
const dy = y - startY
startX = x
startY = y

if (isDragging || Math.abs(x - startX) >= threshold || Math.abs(y - startY) >= threshold) {
const { left, top } = element.getBoundingClientRect()
if (isDragging || Math.abs(dx) > threshold || Math.abs(dy) > threshold) {
const rect = element.getBoundingClientRect()
const { left, top } = rect

if (!isDragging) {
isDragging = true
onStart?.(startX - left, startY - top)
isDragging = true
}

onDrag(x - startX, y - startY, x - left, y - top)
startX = x
startY = y
onDrag(dx, dy, x - left, y - top)
}
}

const click = (e: Event) => {
const onPointerUp = () => {
if (isDragging) {
e.preventDefault()
e.stopPropagation()
isDragging = false
onEnd?.()
}
unsubscribeDocument()
}

const up = () => {
element.style.touchAction = ''
const onClick = (event: MouseEvent) => {
event.stopPropagation()
event.preventDefault()
}

const onTouchMove = (event: TouchEvent) => {
if (isDragging) {
onEnd?.()
event.preventDefault()
}
unsub()
}

document.addEventListener('pointermove', move)
document.addEventListener('pointerup', up)
document.addEventListener('pointerleave', up)
document.addEventListener('click', click, true)

unsub = () => {
document.removeEventListener('pointermove', move)
document.removeEventListener('pointerup', up)
document.removeEventListener('pointerleave', up)
setTimeout(() => {
document.removeEventListener('click', click, true)
}, 10)
document.addEventListener('pointermove', onPointerMove)
document.addEventListener('pointerup', onPointerUp)
document.addEventListener('pointercancel', onPointerUp)
document.addEventListener('touchmove', onTouchMove, { passive: false })
element.addEventListener('click', onClick, { capture: true })

unsubscribeDocument = () => {
document.removeEventListener('pointermove', onPointerMove)
document.removeEventListener('pointerup', onPointerUp)
document.removeEventListener('pointercancel', onPointerUp)
document.removeEventListener('touchmove', onTouchMove)
element.removeEventListener('click', onClick, { capture: true })
}
}

element.addEventListener('pointerdown', down)
element.addEventListener('pointerdown', onPointerDown)

return () => {
unsub()
element.removeEventListener('pointerdown', down)
unsubscribeDocument()
element.removeEventListener('pointerdown', onPointerDown)
}
}

0 comments on commit 2509d07

Please sign in to comment.