Keep the same scene view on link changes

Hi community,

I have an app that has a navigation menu with two links : 3D scene and a form.

When the user clicks on the 3D scene, it shows a threejs scene and loads a glb file into it (in this example I’m showing Suzanne). When the user clicks on form, it goes to another page/link.

My question is : When the user wants to return to the scene, How can I keep the same view (camera position and orientation) as when the user has left it.

I’m using react as my front end stack. What I tried is storing the camera position into the global state, but it causes many renders as soon as I make any action on my scene (raycasting, orbitcontrols, etc.).

any help would be much appreciated


Any thoughts or general guidance !

Thanks in advance

if you are using react make sure to use react-three-fiber if you don’t already do. but now there is no disparity between your dom and the canvas, it’s all just a react tree. your routes are within your scene while your canvas persists. it’s often not a good idea to mount/unmount the canvas between pages due to performance and memory overhead. as for transferring camera coordinates, this becomes a non issue because the camera and the controls also persist.

<Route match="/foo">
  <mesh ... />
</Route>

there’s a starter with nextjs GitHub - pmndrs/react-three-next: React Three Fiber, Nextjs, Tailwind and Styled-components starter

and here’s an example that use component routes: Router transitions - CodeSandbox

if you must unmount canvas between routes, then just fetch the cameras current matrix and apply it once it displays again.

if you are not using fiber, it would defeat the purpose of react. three, as an imperative block, has zero integration with the environment it’s in.

Thanks very much for your input.
I will try these out !

How can I update my state every time the user use OrbitControls (change in camera properties) using R3F?

I have a camera state object that I need to update using Valtio for example.

const state = proxy(
{
cameraPos: {
x: 0,
y: 0,
z: 100,
}
}
)

I need to save the Camera position into the state variable once the user releases the OrbitControls manipulation.

i think something like this, the problem is that orbitcontrols will overwrite any change to the camera, as the name suggests it controls the camera. but calling update i believe will work.

<OrbitControls makeDefault ... />

...
const controls = useThree(state => state.controls)
const camera = useThree(state => state.camera)
useEffect(() => {
  camera.position.set(...)
  if (controls) controls.update()
}, [...])