Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

useZoomEvents.ts 1.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import React, { useEffect, useRef } from "react"
  2. import state from "state"
  3. import * as vec from "utils/vec"
  4. /**
  5. * Capture zoom gestures (pinches, wheels and pans) and send to the state.
  6. * @param ref
  7. * @returns
  8. */
  9. export default function useZoomEvents(
  10. ref: React.MutableRefObject<SVGSVGElement>
  11. ) {
  12. const rTouchDist = useRef(0)
  13. useEffect(() => {
  14. const element = ref.current
  15. if (!element) return
  16. function handleWheel(e: WheelEvent) {
  17. e.preventDefault()
  18. if (e.ctrlKey) {
  19. state.send("ZOOMED_CAMERA", {
  20. delta: e.deltaY,
  21. point: [e.pageX, e.pageY],
  22. })
  23. return
  24. }
  25. state.send("PANNED_CAMERA", {
  26. delta: [e.deltaX, e.deltaY],
  27. point: [e.pageX, e.pageY],
  28. })
  29. }
  30. function handleTouchMove(e: TouchEvent) {
  31. e.preventDefault()
  32. if (e.touches.length === 2) {
  33. const { clientX: x0, clientY: y0 } = e.touches[0]
  34. const { clientX: x1, clientY: y1 } = e.touches[1]
  35. const dist = vec.dist([x0, y0], [x1, y1])
  36. const point = vec.med([x0, y0], [x1, y1])
  37. state.send("WHEELED", {
  38. delta: dist - rTouchDist.current,
  39. point,
  40. })
  41. rTouchDist.current = dist
  42. }
  43. }
  44. element.addEventListener("wheel", handleWheel)
  45. element.addEventListener("touchstart", handleTouchMove)
  46. element.addEventListener("touchmove", handleTouchMove)
  47. return () => {
  48. element.removeEventListener("wheel", handleWheel)
  49. element.removeEventListener("touchstart", handleTouchMove)
  50. element.removeEventListener("touchmove", handleTouchMove)
  51. }
  52. }, [ref])
  53. return {}
  54. }