Easy Animations in Three.js React With Vector3 Lerp

The author
Stephen Castle3 years ago

Imagine you have an object in a 3D scene and you want to change the position. That is pretty easy to do in React Three Fiber or ThreeJS. Just set the position attributes on the object and it will pop to the new location.

Now what if instead of the object popping immediately to the new position you want to animate it moving from the old position to the new position. You could implement this yourself or you could use the fantastically useful lerp method which is on the Three.js Vector3 type. A Vector3 is a class that is used to represent most values which have x, y, and z coordinates in Three.js so you can use it to animate many object transforms like position, scale, or rotation. For this demonstration we will animate the position of a cube.

The lerp method takes as its first argument another vector to interpolate towards, and a second argument called the alpha. You can think of the alpha as the speed at which the position should interpolate towards the new vector.

import * as THREE from "three";
const vec = new THREE.Vector3();
const vec2 = new THREE.Vector3();
vec.lerp(vec2, 0.1);

If you'd like to learn about some of the other features of the Vector3 type check out the documentation here.

Vector3

To use this in a React Three Fiber scene. You need to get a reference to the object you want to animate with useRef. In this case we get a reference to the box. The box object is a Three.js object so it will have a position value which is its self a Vector3 type. This means it has the lerp method and we can call that method with a new target vector and an alpha value to control the speed of interpolation.

Here we are creating a Vector3 called vec every time the x, y, or z values change. Then using that newly created vector, (which has the new x,y,z values from the props) as the first argument to lerp on the position of the box(which is also a Vector3) Lerp will take care of the rest, but don't forget to set the position inside of a useFrame hook so that it can properly update and respond to changes..

const Scene = ({ x, y, z }) => {
  const box = useRef();
  const vec = new THREE.Vector3(x, y, z);
  return (
  //highlight-start
  useFrame(() => group.current.position.lerp(vec, 0.1));
  //highlight-end
  return (
    <Box ref={box}>
      <meshLambertMaterial attach="material" color="white" />
    </Box>
  );
};

Try this demo to see Vector3 and lerp in action. Use the input boxes at the top to change the x, y, and z coordinates and watch the cube animate around the screen. Try changing the Alpha value(second argument in the lerp function) to a value between 0 and 1 and watch how it impacts the speed of the animation.