useAnimationFrame: Step-by-step tutorial

Matt Perry

In this tutorial, we're going to build the useAnimationFrame example step-by-step.

This tutorial 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 APIs we encounter that might be unfamiliar to beginners.

Here's a live demo of the example we're going to be creating:

Loading...

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

Motion is supported by the best in the industry.

Stay in the loop

Subscribe for the latest news & updates.

Stay in the loop

Subscribe for the latest news & updates.

Stay in the loop

Subscribe for the latest news & updates.