Basic Animations
This guide will help you understand refs, useFrame and how to make basic animations with Fiber
This tutorial will assume some React knowledge, and will be based on this starter codesandbox, so just fork it and follow along!
We will build a really simple, continuos animation loop, that will be the basic building block of more advanced animations later on.
useFrame
useFrame
is a Fiber hook that lets you execute code on every frame of Fiber's render loop. This can have a lot of uses, but we will focus on building a simple animation with it.
It's important to remember that Fiber hooks can only be called inside a <Canvas />
parent!
import { useFrame } from 'react-three-fiber'
function MyAnimatedBox() {
useFrame(() => {
console.log("Hey, I'm executing every frame!")
})
return (
<mesh>
<boxBufferGeometry />
<meshBasicMaterial color="royalblue" />
</mesh>
)
}
This loop is the basic building block of our animation, the callback we pass to useFrame
will be executed every frame and it will be passed an object containing the state of our Fiber scene:
For example, we might extract clock information, to know how much time has elapsed in our application, and use that time to animate a value:
useFrame(({ clock }) => {
const a = clock.getElapsedTime()
console.log(a) // the value will be 0 at scene initialization and grow each frame
})
clock
is a THREE.js Clock object, from which we are getting the total elapsed time, which will be key for our animations.
Animating with Refs
It would be tempting to just update the state of our component via setState
and let it change the mesh
via props, but going through state isn't ideal, when dealing with continuos updates, commonly know as transient updates.
Instead, we want to directly mutate our mesh each frame. First, we'll have to get a reference
to it, via the useRef
React hook:
import React from 'react'
function MyAnimatedBox() {
const myMesh = React.useRef()
return (
<mesh ref={myMesh}>
<boxBufferGeometry />
<meshBasicMaterial color="royalblue" />
</mesh>
)
}
myMesh will now hold a reference to the actual THREE.js object, which we can now freely mutate in useFrame
, without having to worry about React:
useFrame(({ clock }) => {
myMesh.current.rotation.x = clock.getElapsedTime()
})
Let's have a closer look:
- We are destructuring
clock
from the argument passed touseFrame
, which we know is the state of our Fiber scene. - We are accessing the
rotation.x
property ofmyMesh.current
object, which is a reference to our mesh object - We are assigning our time-dependendant value
a
to therotation
on thex
axis, meaning our object will now infinitely rotate between -1 and 1 radians around the x axis!
Exercices
- Try
Math.sin(clock.getElapsedTime())
and see how your animation changes
Next steps
Now that you understand the basic technique for animating in Fiber, learn how event works!
If you want to go deeper into animations, check these out:
- Animating with React Spring
- Animating with GSAP
- Add more animation links