useDragScroll.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { useRef, useCallback, MouseEvent } from 'react';
  2. export default function useDragScroll<T extends HTMLElement = HTMLElement>() {
  3. const ref = useRef<T>(null);
  4. const isDragging = useRef(false);
  5. const startX = useRef(0);
  6. const scrollLeft = useRef(0);
  7. const onMouseDown = useCallback((e: MouseEvent) => {
  8. const el = ref.current;
  9. if (!el) return;
  10. isDragging.current = true;
  11. startX.current = e.pageX - el.offsetLeft;
  12. scrollLeft.current = el.scrollLeft;
  13. el.style.cursor = 'grabbing';
  14. }, []);
  15. const onMouseMove = useCallback((e: MouseEvent) => {
  16. if (!isDragging.current) return;
  17. const el = ref.current;
  18. if (!el) return;
  19. e.preventDefault();
  20. const x = e.pageX - el.offsetLeft;
  21. const walk = x - startX.current;
  22. el.scrollLeft = scrollLeft.current - walk;
  23. }, []);
  24. const onMouseUp = useCallback(() => {
  25. isDragging.current = false;
  26. const el = ref.current;
  27. if (el) {
  28. el.style.cursor = 'grab';
  29. }
  30. }, []);
  31. const onMouseLeave = useCallback(() => {
  32. isDragging.current = false;
  33. const el = ref.current;
  34. if (el) {
  35. el.style.cursor = 'grab';
  36. }
  37. }, []);
  38. return {
  39. ref,
  40. onMouseDown,
  41. onMouseMove,
  42. onMouseUp,
  43. onMouseLeave,
  44. };
  45. }