You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

useZoomEvents.ts 1.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
  2. import { useRef } from 'react'
  3. import state from 'state'
  4. import inputs from 'state/inputs'
  5. import vec from 'utils/vec'
  6. import { useGesture } from 'react-use-gesture'
  7. import { fastPinchCamera, fastZoomUpdate } from 'state/hacks'
  8. /**
  9. * Capture zoom gestures (pinches, wheels and pans) and send to the state.
  10. * @param ref
  11. * @returns
  12. */
  13. export default function useZoomEvents() {
  14. const rPinchDa = useRef<number[] | undefined>(undefined)
  15. const rPinchPoint = useRef<number[] | undefined>(undefined)
  16. useGesture(
  17. {
  18. onWheel: ({ event, delta }) => {
  19. if (event.ctrlKey) {
  20. const { point } = inputs.wheel(event as WheelEvent)
  21. fastZoomUpdate(point, delta[1])
  22. return
  23. }
  24. state.send('PANNED_CAMERA', {
  25. delta,
  26. ...inputs.wheel(event as WheelEvent),
  27. })
  28. },
  29. onPinch: ({ pinching, da, origin }) => {
  30. if (!pinching) {
  31. state.send('STOPPED_PINCHING')
  32. rPinchDa.current = undefined
  33. rPinchPoint.current = undefined
  34. return
  35. }
  36. if (rPinchPoint.current === undefined) {
  37. state.send('STARTED_PINCHING')
  38. rPinchDa.current = da
  39. rPinchPoint.current = origin
  40. }
  41. const [distanceDelta] = vec.sub(rPinchDa.current, da)
  42. fastPinchCamera(
  43. origin,
  44. vec.sub(rPinchPoint.current, origin),
  45. distanceDelta
  46. )
  47. rPinchDa.current = da
  48. rPinchPoint.current = origin
  49. },
  50. },
  51. {
  52. domTarget: document.body,
  53. eventOptions: { passive: false },
  54. }
  55. )
  56. }