Skip to content

Instantly share code, notes, and snippets.

@neftaly
Created July 9, 2020 03:45
Show Gist options
  • Save neftaly/1f619b20921b431f7dc5942fe87fff49 to your computer and use it in GitHub Desktop.
Save neftaly/1f619b20921b431f7dc5942fe87fff49 to your computer and use it in GitHub Desktop.
rstream-gestures multitouch with react
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