v10 deployment.Basic Animations
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 small, continuous 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 an 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>
<boxGeometry />
<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 can read timing information directly off the state to know how much time has elapsed in our application, and use that to animate a value:
useFrame((state) => {
const a = state.elapsed
console.log(a) // the value will be ~0 at scene initialization and grow each frame
})
state.elapsed is the number of seconds since the first frame. The frame state also gives you state.delta (seconds since the previous frame), state.time (the RAF timestamp), and state.frame (frame count) — these replace the old state.clock from v9.
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 continuous updates, commonly known 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}>
<boxGeometry />
<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((state) => {
myMesh.current.rotation.x = state.elapsed
})
Let's have a closer look:
- We are reading
elapsedfrom thestatepassed touseFrame, which we know is the state of our Fiber scene. - We are accessing the
rotation.xproperty ofmyMesh.currentobject, which is a reference to our mesh object - We are assigning our time-dependent value to the
rotationon thexaxis, meaning our object will now infinitely rotate around the x axis!
Exercises
- Try
Math.sin(state.elapsed)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: