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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import React, { useEffect, useRef } from 'react'
  2. import state from 'state'
  3. import inputs from 'state/inputs'
  4. import * as vec from 'utils/vec'
  5. import { useGesture } from 'react-use-gesture'
  6. /**
  7. * Capture zoom gestures (pinches, wheels and pans) and send to the state.
  8. * @param ref
  9. * @returns
  10. */
  11. export default function useZoomEvents() {
  12. const rPinchDa = useRef<number[] | undefined>(undefined)
  13. const rPinchPoint = useRef<number[] | undefined>(undefined)
  14. useGesture(
  15. {
  16. onWheel: ({ event, delta }) => {
  17. if (event.ctrlKey) {
  18. state.send('ZOOMED_CAMERA', {
  19. delta: delta[1],
  20. ...inputs.wheel(event as WheelEvent),
  21. })
  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, angleDelta] = vec.sub(rPinchDa.current, da)
  42. state.send('PINCHED', {
  43. delta: vec.sub(rPinchPoint.current, origin),
  44. point: origin,
  45. distanceDelta,
  46. angleDelta,
  47. })
  48. rPinchDa.current = da
  49. rPinchPoint.current = origin
  50. },
  51. },
  52. {
  53. domTarget: document.body,
  54. eventOptions: { passive: false },
  55. }
  56. )
  57. }