Fundamentals
Core
Master
Shaders
Animations
Animations are keys to bring your 3D scene to life. They can be triggered by user interactions, scroll or time based and applied to 3D objects, lights and cameras.
Mastering animations is a key skill to create immersive experiences. The more techniques you know, the more you can express your creativity.
Note: The 3D model animations are covered in the models chapter.
Lerp
Lerp is a mathematical function that interpolates between two values. It is useful to animate a value from one point to another.
const value = THREE.MathUtils.lerp(start, end, t);
The first parameter is the start value, the second parameter is the end value and the third parameter is the interpolation factor between 0 and 1.
The closer the interpolation factor is to 0, the slower the animation will be. The closer the interpolation factor is to 1, the faster the animation will reach the end or target value.
Let's experiment it on the AnimatedBox
component from the starter pack.
The component has a boxPositions
array that contains the positions of the box at different times. Let's add a useFrame
hook to update the position of the box based on the time:
import { RoundedBox } from "@react-three/drei"; import { useRef } from "react"; export const AnimatedBox = ({ boxPositions, ...props }) => { const box = useRef(); useFrame(({ clock }) => { const seconds = parseInt(clock.getElapsedTime()); const targetPosition = boxPositions[seconds % boxPositions.length]; box.current.position.x = targetPosition.x; box.current.position.y = targetPosition.y; box.current.position.z = targetPosition.z; }); // ... };
Here our box is not animated. It teleports from one position to another. Let's use the lerp
function to animate it:
import * as THREE from "three"; // ... export const AnimatedBox = ({ boxPositions, ...props }) => { const box = useRef(); useFrame(({ clock }) => { const seconds = parseInt(clock.getElapsedTime()); const targetPosition = boxPositions[seconds % boxPositions.length]; box.current.position.x = THREE.MathUtils.lerp( box.current.position.x, targetPosition.x, 0.05 ); box.current.position.y = THREE.MathUtils.lerp( box.current.position.y, targetPosition.y, 0.05 ); box.current.position.z = THREE.MathUtils.lerp( box.current.position.z, targetPosition.z, 0.05 ); }); // ... };
The box is now animated. It moves smoothly from one position to another.
The Vector3
class has a lerp
method that can be used instead of the THREE.MathUtils.lerp
function:
// box.current.position.x = THREE.MathUtils.lerp( // box.current.position.x, // targetPosition.x, // 0.05 // ); // box.current.position.y = THREE.MathUtils.lerp( // box.current.position.y, // targetPosition.y, // 0.05 // ); // box.current.position.z = THREE.MathUtils.lerp( // box.current.position.z, // targetPosition.z, // 0.05 // ); box.current.position.lerp(targetPosition, 0.05);
That's a lot of lines saved for the same result!
Don't hesitate to play with the time and to lerp on other properties like the rotation
or the scale
to try different effects.
Float
Float is a wrapper component from Drei library to simply give the impression that an object is floating.
It contains the following props:
speed
: Animation speed, defaults to 1rotationIntensity
: XYZ rotation intensity, defaults to 1floatIntensity
: Up/down float intensity, works like a multiplier with floatingRange,defaults to 1floatingRange
: Range of y-axis values the object will float within, defaults to [-0.1,0.1]
Let's make our Duck float in Experience.jsx
:
End of lesson preview
To get access to the entire lesson, you need to purchase the course.