event.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. export const getOffset = (ev: MouseEvent | TouchEvent, dom = ev.target! as HTMLElement, ndx = 0) => {
  2. const event = ev instanceof TouchEvent ? ev.changedTouches[ndx] : ev
  3. const rect = dom.getBoundingClientRect();
  4. const offsetX = event.clientX - rect.left;
  5. const offsetY = event.clientY - rect.top;
  6. return {
  7. x: offsetX,
  8. y: offsetY,
  9. };
  10. };
  11. export type Pos = { x: number; y: number };
  12. type DragProps = {
  13. move?: (info: Record<'start' | 'prev' | 'end', Pos> & {ev: PointerEvent}) => void,
  14. down?: (pos: Pos, ev: PointerEvent) => void,
  15. up?: (pos: Pos, ev: PointerEvent) => void,
  16. }
  17. export const dragListener = (dom: HTMLElement, props: DragProps | DragProps['move'] = {}) => {
  18. if (typeof props === 'function') {
  19. props = { move: props }
  20. }
  21. const { move, up, down } = props
  22. const mount = document.documentElement
  23. if (!move && !up && !down) return () => {}
  24. let moveHandler: any, endHandler: any
  25. const downHandler = (ev: PointerEvent) => {
  26. const start = getOffset(ev, dom)
  27. let prev = start
  28. down && down(start, ev)
  29. // ev.preventDefault();
  30. moveHandler = (ev: PointerEvent) => {
  31. const end = getOffset(ev, dom)
  32. move!({start, end, prev, ev})
  33. prev = end
  34. // ev.preventDefault();
  35. }
  36. endHandler = (ev: PointerEvent) => {
  37. up && up(getOffset(ev, dom), ev)
  38. mount.removeEventListener('pointermove', moveHandler);
  39. mount.removeEventListener('pointerup', endHandler);
  40. // ev.preventDefault();
  41. }
  42. move && mount.addEventListener('pointermove', moveHandler, { passive: false })
  43. mount.addEventListener('pointerup', endHandler, { passive: false })
  44. }
  45. dom.addEventListener('pointerdown', downHandler, { passive: false });
  46. return () => {
  47. dom.removeEventListener('pointerdown', downHandler);
  48. moveHandler && mount.removeEventListener('pointermove', moveHandler);
  49. endHandler && mount.removeEventListener('pointerup', endHandler);
  50. }
  51. }
  52. export const clickListener = (dom: HTMLDivElement, callback: (position: Pos, ev: PointerEvent) => void, button = 0) => {
  53. let downTime = 0;
  54. let move = false
  55. return dragListener(dom, {
  56. down(_, ev) {
  57. if (ev.button !== button) return;
  58. downTime = Date.now();
  59. },
  60. up(position, ev) {
  61. const prevMove = move
  62. move = false
  63. if (prevMove || !downTime) return;
  64. if (Date.now() - downTime <= 300) {
  65. callback(position, ev)
  66. }
  67. downTime = 0
  68. },
  69. });
  70. };