useAnimationFrame example: Step-by-step
In this tutorial, we'll build the useAnimationFrame example step-by-step.
This example is rated 1/5 difficulty, which means we'll spend some time explaining the Motion APIs that we've chosen to use (and why), and also any browser JavaScript APIs we encounter that might be unfamiliar to beginners.
Introduction
The useAnimationFrame
example shows how to create complex continuous animations using Motion's useAnimationFrame
hook. This hook provides a way to run a function on every frame, perfect for creating dynamic, math-based animations that need to run continuously.
Get started
Let's start with the basic structure of our 3D cube:
export default function UseAnimationFrame() {
return (
<div className="container">
<div className="cube">
<div className="side front" />
<div className="side left" />
<div className="side right" />
<div className="side top" />
<div className="side bottom" />
<div className="side back" />
</div>
</div>
)
}
Let's animate!
Import from Motion
First, we'll import the necessary hooks:
import { useAnimationFrame } from "motion/react"
import { useRef } from "react"
Setting up direct DOM manipulation
For this animation, we're calculating our own transform
values every animation frame. So we can directly assign the transform
property to the DOM element.
For this, we need a reference to our cube element:
export default function UseAnimationFrame() {
const ref = useRef<HTMLDivElement>(null)
return (
<div className="container">
<div className="cube" ref={ref}>
{/* ... cube sides ... */}
</div>
</div>
)
}
Creating the continuous animation
Now, let's add the frame-by-frame animation using useAnimationFrame
. This hook runs a function on every animation frame, providing a timestamp we can use to create smooth continuous motion:
useAnimationFrame((t) => {
if (!ref.current) return
const rotate = Math.sin(t / 10000) * 200
const y = (1 + Math.sin(t / 1000)) * -50
ref.current.style.transform = `translateY(${y}px) rotateX(${rotate}deg) rotateY(${rotate}deg)`
})
The timestamp, t
, increases continuously, allowing us to create cyclical motion. We use Math.sin
to create smooth oscillating values between -1 and 1.
For rotation: t / 10000
creates a slow cycle, multiplied by 200 for a -200° to 200° range.
For vertical movement (y
): t / 1000
creates a faster cycle, transformed to move between 0 and -100px.
Conclusion
In this tutorial, we learned how to:
- Use refs for direct DOM manipulation in React
- Create frame-by-frame animations with
useAnimationFrame
- Generate smooth motion using mathematical functions
- Combine multiple transforms for rich 3D effects
- Optimize performance by bypassing React's state system
Tutorial Project
We're currently working on adding a tutorial for every example on the Motion Examples website. So far, 12% of examples have a tutorial.