Accessing the Camera in React Three Fiber out of the canvas

Hi,

I am interested in accessing the camera of three js outside of the canvas component. I basically have a configuration file and want to give the user the option to set the current camera orientation as the config orientation, so accessing the camera would give me an easy way of making that feature happen.

Is it possible to get the camera info this way?

not sure what you mean by outside, the camera only exists within the canvas.

you can access it after the canvas has been created

<Canvas onCreated={state => {
  // state.camera.fov = 45 

within every component

<Canvas>
  <Foo />

function Foo() {
  const camera = useThree(state => state.camera)

you could also use a declarative camera

import { PerspectiveCamera } '@react-three/drei'

const config = { fov: 35, position: [0, 0, 10] }

<Canvas>
  <PerspectiveCamera {...config} />

I meant accessing it outside the canvas component. Could I use a ref to accomplish this?

you can ofc create a new THREE.PerspectiveCamera, even drop that right into <Canvas camera={myOwn} but imo that is not clean, it goes against separation of concern. i would suggest you don’t do that since all it will cause is problems.

the outside shouldn’t hold a reference to something that happens within the canvas, it should hold state to which canvas internals react to. that is fundamentally react: the view is an outcome of state. for instance you have a store or a state model that holds position as an array of [x,y,z]. you change it and the camera within canvas will react and pick up these values.

an example using a state manager, it will animate towards any point where state tells it to go:

import create from 'zustand'

const useStore = create(set => ({
  position: [0, 0, 10],
  setPosition: position => set({ position })
}))

function App() {
  const setPosition = useStore(state => state.setPosition)
  return (
    <>
      <Canvas>
        <MyCameraReactsToStateChanges />
      </Canvas>
      <button onClick={() => setPosition([0, 10, 20])}>click me</button>
  </>
  )
}

function MyCameraReactsToStateChanges() {
  const [x, y, z] = useStore(state => state.position)
  useFrame(state => {
    state.camera.lerp({ x, y, z }, 0.1)
    state.camera.lookAt(0, 0, 0)
  })
}

Hello Paul, thank you so much for that. Since there’s no easing with lerp. Is there a way to animate the camera with react-spring?