Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import { useCallback } from 'react'
import * as THREE from "three"
import { useSpring } from "react-spring"
export interface OrbitParam {
position: THREE.Vector3,
target: THREE.Vector3,
up: THREE.Vector3,
fov: number,
zoom: number
}
const align = (src: THREE.Vector3, guide: THREE.Vector3): THREE.Vector3 => {
src.cross(guide.normalize())
return guide.cross(src)
}
export const useOrbitInterpolation = ({
from, to, reset = false, onStart, onFrame, onRest, immediate = false
}: {
from?: OrbitParam,
to: OrbitParam,
reset?: boolean,
onStart?: () => void,
onFrame?: (OrbitParam) => void,
onRest?: () => void,
immediate?: boolean
}) => {
const makeParam = src => {
const sub = new THREE.Vector3().subVectors(src.target, src.position)
return {
target: to.target.toArray(),
heading: sub.clone().normalize().toArray(),
distance: sub.length(),
up: to.up.toArray(),
fov: to.fov,
zoom: to.zoom
}
}
const [value, set] = useSpring(() => ({
from: from && makeParam(from),
to: makeParam(to),
reset,
onFrame: props => {
const target = new THREE.Vector3().fromArray(props.target)
const position = target.clone().addScaledVector(new THREE.Vector3().fromArray(props.heading), -props.distance)
const up = align(new THREE.Vector3().fromArray(props.up), new THREE.Vector3().subVectors(target, position))
onFrame({ position, target, up, fov: props.fov, zoom: props.zoom })
},
onStart,
onRest
}))
const reInterpolate = useCallback(({ from, to, reset }: {
from?: OrbitParam,
to: OrbitParam,
reset?: boolean
}) => {
set({
from: from && makeParam(from),
to: makeParam(to),
reset,
})
}, [set])
return reInterpolate
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment