|
|
import _extends from '@babel/runtime/helpers/esm/extends'; |
|
|
import * as React from 'react'; |
|
|
import { MathUtils } from 'three'; |
|
|
import { useThree, useFrame } from '@react-three/fiber'; |
|
|
import { useGesture } from '@use-gesture/react'; |
|
|
import { easing } from 'maath'; |
|
|
|
|
|
function PresentationControls({ |
|
|
enabled = true, |
|
|
snap, |
|
|
global, |
|
|
domElement, |
|
|
cursor = true, |
|
|
children, |
|
|
speed = 1, |
|
|
rotation = [0, 0, 0], |
|
|
zoom = 1, |
|
|
polar = [0, Math.PI / 2], |
|
|
azimuth = [-Infinity, Infinity], |
|
|
damping = 0.25 |
|
|
}) { |
|
|
const events = useThree(state => state.events); |
|
|
const gl = useThree(state => state.gl); |
|
|
const explDomElement = domElement || events.connected || gl.domElement; |
|
|
const { |
|
|
size |
|
|
} = useThree(); |
|
|
const rPolar = React.useMemo(() => [rotation[0] + polar[0], rotation[0] + polar[1]], [rotation[0], polar[0], polar[1]]); |
|
|
const rAzimuth = React.useMemo(() => [rotation[1] + azimuth[0], rotation[1] + azimuth[1]], [rotation[1], azimuth[0], azimuth[1]]); |
|
|
const rInitial = React.useMemo(() => [MathUtils.clamp(rotation[0], ...rPolar), MathUtils.clamp(rotation[1], ...rAzimuth), rotation[2]], [rotation[0], rotation[1], rotation[2], rPolar, rAzimuth]); |
|
|
React.useEffect(() => { |
|
|
if (global && cursor && enabled) { |
|
|
explDomElement.style.cursor = 'grab'; |
|
|
gl.domElement.style.cursor = ''; |
|
|
return () => { |
|
|
explDomElement.style.cursor = 'default'; |
|
|
gl.domElement.style.cursor = 'default'; |
|
|
}; |
|
|
} |
|
|
}, [global, cursor, explDomElement, enabled]); |
|
|
const [animation] = React.useState({ |
|
|
scale: 1, |
|
|
rotation: rInitial, |
|
|
damping |
|
|
}); |
|
|
const ref = React.useRef(null); |
|
|
useFrame((state, delta) => { |
|
|
easing.damp3(ref.current.scale, animation.scale, animation.damping, delta); |
|
|
easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta); |
|
|
}); |
|
|
const bind = useGesture({ |
|
|
onHover: ({ |
|
|
last |
|
|
}) => { |
|
|
if (cursor && !global && enabled) explDomElement.style.cursor = last ? 'auto' : 'grab'; |
|
|
}, |
|
|
onDrag: ({ |
|
|
down, |
|
|
delta: [x, y], |
|
|
memo: [oldY, oldX] = animation.rotation || rInitial |
|
|
}) => { |
|
|
if (!enabled) return [y, x]; |
|
|
if (cursor) explDomElement.style.cursor = down ? 'grabbing' : 'grab'; |
|
|
x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth); |
|
|
y = MathUtils.clamp(oldY + y / size.height * Math.PI * speed, ...rPolar); |
|
|
animation.scale = down && y > rPolar[1] / 2 ? zoom : 1; |
|
|
animation.rotation = snap && !down ? rInitial : [y, x, 0]; |
|
|
animation.damping = snap && !down && typeof snap !== 'boolean' ? snap : damping; |
|
|
return [y, x]; |
|
|
} |
|
|
}, { |
|
|
target: global ? explDomElement : undefined |
|
|
}); |
|
|
return React.createElement("group", _extends({ |
|
|
ref: ref |
|
|
}, bind == null ? void 0 : bind()), children); |
|
|
} |
|
|
|
|
|
export { PresentationControls }; |
|
|
|