What's the correct way to animate the camera using react-spring? #505
Replies: 7 comments 12 replies
-
I gave it a shot https://codesandbox.io/s/r3f-basic-demo-nmm2s?file=/src/index.js |
Beta Was this translation helpful? Give feedback.
-
i dont know, i find it unusual to have a usespring animate on its own. generally i think this approach is problematic. controls control the camera, you cant animate the camera any longer. if you want to animate you must first disable controls. it seems to work in this case, but thats probably accidental. controls unfortunately do not allow programatic steering - which is a feature people have been asking for years but threejs doesnt want to. |
Beta Was this translation helpful? Give feedback.
-
Why do you think it's problematic to just useSpring? I may be missing some react-spring fundamentals |
Beta Was this translation helpful? Give feedback.
-
Hi I want to use the gsap scrollTrigger to animate the position of my camera in react three fiber can someone help? |
Beta Was this translation helpful? Give feedback.
-
since v9 dropped, I've stopped trying to update the camera via a spring. Instead, what I've started doing is using a Below is the source code for the component, and here is an example codesandbox of the technique. interface ZoomInProps {
from: number
to: number
onRest?: () => void
children: React.ReactNode
}
export const ZoomIn = ({ from, to, onRest, children }: ZoomInProps) => {
const { position } = useSpring({
position: [0, 0, -to],
from: { position: [0, 0, -from] },
onRest
})
return <animated.group position={(position as unknown) as Vector3}>{children}</animated.group>
} |
Beta Was this translation helpful? Give feedback.
-
I found @neefrehman suggestion super useful, I animate the entire composition to make the illusion of the camera being animated. In my case I make the transition on click a element and then allow freely move the camera under my constrains. Nonetheless, it is important to highlight that:
https://www.loom.com/share/6d3cdb346367475892b06a02acc059bb import React, { forwardRef, Suspense, useRef, useState } from 'react'
import * as THREE from 'three'
import {
Canvas,
Color,
MeshProps,
ThreeEvent,
useFrame,
useThree,
} from '@react-three/fiber'
import { useTheme } from 'styled-components'
import { OrbitControls, QuadraticBezierLine, Stars, Text } from '@react-three/drei'
import { useSpring, animated } from '@react-spring/three'
// ...
export const PathwayScene = ({ pitstops, onClickPitstop }: PathwaySceneProps) => {
const theme = useTheme()
return (
<Canvas>
<Pathway3D pitstops={pitstops} onClickPitstop={onClickPitstop} theme={theme} />
<ambientLight intensity={0.1} color="white" />
<directionalLight position={[0, 5, 5]} />
<Controls />
<Stars />
</Canvas>
)
}
const Controls = () => {
const { gl, camera } = useThree()
return (
/**
* The args value with camera and gl are required to be passed to the OrbitControls
* in order to allow the illusion of camera re-focus to work when click a pitstop.
*/
<OrbitControls
makeDefault
target={[0, 0, 0]}
args={[camera, gl.domElement]}
maxDistance={10}
minDistance={3}
// vertical angle of the orbit
minPolarAngle={angleToRadians(45)}
maxPolarAngle={angleToRadians(80)}
// horizontal angle of the orbit
minAzimuthAngle={angleToRadians(-180)}
maxAzimuthAngle={angleToRadians(180)}
/>
)
}
const AnimatedGroup = ({ children }: { children: React.ReactNode }) => {
const [focusPoint, setFocusPoint] = useState({
from: [0, -3, -100],
to: [0, 0, 0],
})
const { position } = useSpring({
position: focusPoint.to,
from: { position: focusPoint.from },
})
const newPosition = position as unknown as Vector3
const handleOnClick = (e: ThreeEvent<MouseEvent>) => {
const objectPosition = e.object.position.toArray()
const newFocusPoint = {
from: [focusPoint.to[0], focusPoint.to[1], focusPoint.to[2]],
to: [objectPosition[0] * -1, objectPosition[1], objectPosition[2] * -1],
}
if (!e.object.userData.pitstopVariant) return
setFocusPoint(newFocusPoint)
}
return (
<animated.group position={newPosition} onClick={handleOnClick}>
{children}
</animated.group>
)
}
const Pathway3D = ({
pitstops,
theme,
}: PathwaySceneProps & { theme: DefaultTheme }) => {
const self = useRef<Partial<{ [key: string]: THREE.Mesh }>>({}).current
const saveRef = (key: string) => (r: THREE.Mesh) => {
self[key] = r
}
return (
<Suspense fallback={null}>
<AnimatedGroup>
{/* render my whole composition */}
</AnimatedGroup>
</Suspense>
)
}
const Connector = ({
start,
end,
color,
...props
}: MeshProps & {
start?: THREE.Mesh
end?: THREE.Mesh
color: string
}) => {
// ...
}
const Pitstop = forwardRef(
(
{ color, label, ...props }: MeshProps & { color?: Color; label?: string },
ref: any
) => {
// ...
) |
Beta Was this translation helpful? Give feedback.
-
I've had success using an |
Beta Was this translation helpful? Give feedback.
-
If I wanted to use
react-spring
to animate the camera position withOrbitControls
how should I do this? I've been searching various issues but haven't seen any solutions yet.Before I have managed to do this by directly accessing
z.value
like below, but it looks like this will no longer be possible with react-spring @9.0
, having tested the beta.Beta Was this translation helpful? Give feedback.
All reactions