Skip to content

Instantly share code, notes, and snippets.

@mfcodeworks
Created June 18, 2020 16:53
Show Gist options
  • Save mfcodeworks/eba18fa9a04e4bba8ce2d046f61a8806 to your computer and use it in GitHub Desktop.
Save mfcodeworks/eba18fa9a04e4bba8ce2d046f61a8806 to your computer and use it in GitHub Desktop.
Drag HTML Elements
const {
fromEvent,
interval,
merge
} = rxjs
const {
takeUntil,
repeat,
throttle,
switchMap,
map,
tap
} = rxjs.operators
// Get target
const el = document.querySelector('.draggable');
// Get events
const down$ = merge(
fromEvent(el, 'mousedown'),
fromEvent(el, 'touchstart')
);
const move$ = merge(
fromEvent(document, 'mousemove'),
fromEvent(document, 'touchmove')
);
const up$ = merge(
fromEvent(el, 'mouseup'),
fromEvent(el, 'touchend')
);
// Process dragging
const drag$ = down$.pipe(
// Add offset to touch events
map(ev => ev instanceof MouseEvent
? ev : Object.assign(ev, {
offsetX: Math.floor(ev.touches[0].clientX) - ev.target.offsetLeft,
offsetY: Math.floor(ev.touches[0].clientY) - ev.target.offsetTop
})
),
switchMap(start => move$.pipe(
// Slow to 59 events per second (60~ fps)
throttle(() => interval(17)),
// Prevent further handling of events
tap(move => move.preventDefault()),
// Map to new posiiton
map(move => {
return move instanceof MouseEvent ? ({
left: move.clientX - start.offsetX,
top: move.clientY - start.offsetY
}) : ({
left: move.targetTouches[0].clientX - start.offsetX,
top: move.targetTouches[0].clientY - start.offsetX
})
})
)),
// Apply new posiiton
tap(e => {
el.style.top = `${e.top}px`;
el.style.left = `${e.left}px`;
}),
// Track dragging until user lets go
takeUntil(up$),
// Repeat even after initial drag
repeat()
)
// Handle dragging
drag$.subscribe()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment