Created
July 8, 2021 18:09
-
-
Save seflless/810f907673df26fe551b996b1d053897 to your computer and use it in GitHub Desktop.
useGesture Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import appActor from '../state/actors/app'; | |
import { useGesture } from '@use-gesture/react' | |
import { useEffect, useRef } from "react" | |
import { getCamera } from "../cameras/usePanZoom"; | |
export function usePanZoomEvents() { | |
const panZoomStartPositionInWorldSpace = useRef() | |
console.log("usepanzoom"); | |
useEffect(() => { | |
// As per the use-react-gesture document on pinching, we disable the safari gesture events | |
// https://use-gesture.netlify.app/docs/hooks/ | |
document.addEventListener('gesturestart', e => e.preventDefault()) | |
document.addEventListener('gesturechange', e => e.preventDefault()) | |
const eventsOfInterest = [ | |
"pointerdown", | |
"pointermove", | |
"pointerup" | |
]; | |
const eventListeners = eventsOfInterest.map(eventName => { | |
const listener = (event) => { | |
appActor.send(event) | |
}; | |
document.addEventListener(eventName, listener); | |
return listener; | |
}) | |
return () => { | |
eventListeners.forEach((listener, index) => { | |
document.removeEventListener(eventsOfInterest[index], listener); | |
}); | |
} | |
}, []) | |
useGesture( | |
{ | |
onWheel: ({ event, delta }) => { | |
getCamera().setPosition( | |
getCamera().x + delta[0] * getCamera().z, | |
getCamera().y + delta[1] * getCamera().z, | |
getCamera().z | |
); | |
// This only gets called when a pure translation occurs, and happens from | |
// "mousewheel" gestures. On touchpads | |
appActor.send("Camera_Panned"); | |
}, | |
onPinch: ({ pinching, da, origin, offset, ...rest }) => { | |
// Notify app state machine a session of mix camera panning and/or zooming has stopped | |
if (!pinching) { | |
appActor.send("Camera_PanZoom_Stopped"); | |
panZoomStartPositionInWorldSpace.current = undefined | |
return; | |
} | |
// Notify app state machine a session of mix camera panning and/or zooming has started | |
if (panZoomStartPositionInWorldSpace.current === undefined) { | |
appActor.send("Camera_PanZoom_Started"); | |
// Remember the starting world position of the pinch gesture | |
panZoomStartPositionInWorldSpace.current = getCamera().screenToWorld({ x: origin[0], y: origin[1] }); | |
} | |
// Calculate new zoom | |
// The 320 is a magic number that we can tweak more to get the exact zoom speed we want | |
// I wish it was more exact, as in where your fingers start in world coordinates are where | |
// they end in world coordinates | |
let deltaZ = -rest.delta[0] / 320.0 * getCamera().z; | |
if (getCamera().z + deltaZ < getCamera().minZoom) { | |
deltaZ = getCamera().minZoom - getCamera().z; | |
} else if (getCamera().z + deltaZ > getCamera().maxZoom) { | |
deltaZ = getCamera().maxZoom - getCamera().z; | |
} | |
const newZ = getCamera().z + deltaZ; | |
// Calculate new translation | |
const cameraSpace = { | |
x: -(origin[0] - window.innerWidth / 2.0) * newZ + panZoomStartPositionInWorldSpace.current.x, | |
y: -(origin[1] - window.innerHeight / 2.0) * newZ + panZoomStartPositionInWorldSpace.current.y | |
} | |
// Now set it, this will trigger all hooks that listen for camera position changes | |
getCamera().setPosition(cameraSpace.x, cameraSpace.y, newZ); | |
}, | |
}, | |
{ | |
domTarget: document.querySelector(".tool-background"), | |
eventOptions: { passive: false } | |
} | |
) | |
} | |
// We nest this element which actually does all the event binding, so that hooks like | |
// useGesture don't trigger renders on every pan/zoom related event | |
function DocumentEventsInner() { | |
usePanZoomEvents(); | |
return <></> | |
} | |
// Include this element to setup all the app events that are attached to document.body or window | |
function DocumentEvents() { | |
return <DocumentEventsInner /> | |
} | |
export default DocumentEvents; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment