Created
July 9, 2020 03:45
-
-
Save neftaly/1f619b20921b431f7dc5942fe87fff49 to your computer and use it in GitHub Desktop.
rstream-gestures multitouch with react
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 React, { useEffect } from 'react' | |
import { useThree } from 'react-three-fiber' | |
import { GestureType, gestureStream } from '@thi.ng/rstream-gestures' | |
import { map } from '@thi.ng/transducers' | |
import { tryCatch } from 'ramda' | |
// Calculate the difference between 2 [x,y] vectors | |
const calcDelta = (key, a, b) => [a[key][0] - b[key][0], a[key][1] - b[key][1]] | |
// Calculate the angle and distance between 2 pointers | |
const calcPinch = (a, b) => { | |
const start = calcDelta('start', a, b) | |
const current = calcDelta('pos', a, b) | |
// Change in angle since first event (radians) | |
const angleDelta = Math.atan2(...start) - Math.atan2(...current) | |
// Change in distance since first event (ratio) | |
const distanceScale = Math.hypot(...current) / Math.hypot(...start) | |
return [angleDelta, distanceScale] | |
} | |
const ControlRig = ({ | |
gestureComponentRef, | |
handleWheel, | |
handlePan, | |
handlePinch, | |
handlePress, | |
handleRotate, | |
handleTap | |
}) => { | |
const three = useThree() | |
useEffect(() => { | |
const srcElement = gestureComponentRef.current | |
if (!srcElement) return // Initial mount | |
const gestures = gestureStream(srcElement) | |
const handler = event => { | |
const { type, buttons, isTouch, active, zoomDelta } = event | |
// Event types | |
const isStart = type === GestureType.START | |
const isMove = type === GestureType.MOVE | |
const isDrag = type === GestureType.DRAG | |
const isEnd = type === GestureType.END | |
const isZoom = type === GestureType.ZOOM | |
// Mouse buttons | |
const isLeftMouse = !isTouch && buttons & 1 | |
const isRightMouse = !isTouch && buttons & 2 | |
const isMiddleMouse = !isTouch && buttons & 4 | |
// Wheel | |
if (isZoom) { | |
console.log('zoom', zoomDelta) | |
return | |
} | |
// Multitouch "Pinch" gesture | |
const isPinch = isTouch && isDrag && buttons === 2 | |
if (isPinch) { | |
const [angle, distance] = calcPinch(...active) | |
console.log('pinch', angle, distance) | |
return | |
} | |
// console.log(event) | |
} | |
gestures.subscribe(map(tryCatch(handler, console.warn))) | |
return () => gestures.done() // Unmount | |
}, []) | |
return null | |
} | |
export default ControlRig |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment