Search code examples
reactjsthree.jsreact-three-fiber

React three fiber - Tween Camera


I want to tween my camera, from Position A to B. I did it a few times using react spring with a little workaround:

import { useSpring } from "react-spring/three";

const springProps = useSpring({
config: { duration: 1000, easing: easings.easeCubicInOut },
to: {
  position: props.position,
  lookAt: props.lookAt,
  offset: props.offset,
},
onRest: (ya) => {
  if (props.enableOrbit) {
    props.parentStateModifier({ enableOrbit: true });
  }
},
});

useFrame(({ clock, camera, mouse }) => {
  camera.position.x = springProps.position.payload[0].value;
  camera.position.y = springProps.position.payload[1].value;
  camera.position.z = springProps.position.payload[2].value;

  camera.lookAt(
    springProps.lookAt.payload[0].value,
    springProps.lookAt.payload[1].value,
    springProps.lookAt.payload[2].value
  );
  camera.updateProjectionMatrix();
});

This was'nt a very good approach, but it worked.

I am now using @react-spring/three and its not working anymore. "payload" is undefined now and I was able to get the coordinates by calling springProps.x.animation.values[0]._value

But values is empty when not animating. I'm sure there must be a better way to animate camera.

I love react spring for animating three meshes. I hope I can use it for my camera as well.


Solution

  • Ok, I managed to update my code so that my camera is animating again:

    const { gl, camera } = useThree();
    
    const springProps = useSpring({
      config: { duration: 1000, easing: easings.easeCubic },
      from: {
        x: - 0.1,
        y: - 0.1,
        z: - 0.1,
        lookAtX: camera.lookAt.x - 0.1,
        lookAtY: camera.lookAt.y - 0.1,
        lookAtZ: camera.lookAt.z - 0.1,
      },
      to: {
        x: cameraData.position[0],
        y: cameraData.position[1],
        z: cameraData.position[2],
        lookAtX: cameraData.lookAt[0],
        lookAtY: cameraData.lookAt[1],
        lookAtZ: cameraData.lookAt[2],
      }
    });
    
    useFrame((state, delta) => {
      if (!orbit) {
        camera.position.x = springProps.x.animation.values[0]._value;
        camera.position.y = springProps.y.animation.values[0]._value;
        camera.position.z = springProps.z.animation.values[0]._value;
        camera.lookAt(
          springProps.lookAtX.animation.values[0]._value,
          springProps.lookAtY.animation.values[0]._value,
          springProps.lookAtZ.animation.values[0]._value
        );
      }
    });
    

    Problem is, that if the from and to values are the same, values[0] will be undefined. So for example this will not work with my code:

    from: {
      x: 0
      y: 0,
      z: 0,
    },
    to: {
      x: 0,
      y: 2,
      z: 4,
    }
    

    because x has the same value. I hope someone can provide a better way of animating cameras in r3f.