Follow pointer with spring example: Step-by-step
In this tutorial, we'll build the Follow pointer with spring example step-by-step.
This example is rated 2/5 difficulty, which means we'll spend some time explaining the Motion APIs we've chosen to use, but it assumes familiarity with JavaScript as a language.
Introduction
The Follow Pointer with Spring example shows how to make an element smoothly follow your cursor with a spring-like motion. This creates a natural, physical feeling as the element trails behind your mouse movements.
This example uses two key Motion APIs:
useSpring
- To create spring physics-based animationframe
- For efficient, batched DOM reads and writes
Spring animations are a great way to add natural motion to your UI because they mimic the behavior of real-world physics. Unlike linear or easing animations, springs respond to changes in velocity, making the motion feel more organic, especially when following user input like mouse movement.
Get started
Let's start by creating a basic component with a ball that will follow our pointer:
"use client"
import { motion } from "motion/react"
import { useRef } from "react"
export default function Drag() {
const ref = useRef<HTMLDivElement>(null)
return <motion.div ref={ref} style={ball} />
}
const ball = {
width: 100,
height: 100,
backgroundColor: "#5686F5",
borderRadius: "50%",
}
This gives us a simple blue circle on the screen, but it doesn't follow our pointer yet.
Let's animate!
Import from Motion
First, we need to import the additional Motion APIs we'll be using:
import { frame, motion, useSpring } from "motion/react"
Creating the spring motion values
Now we'll create a custom hook that will handle the pointer-following logic:
function useFollowPointer(ref) {
const x = useSpring(0)
const y = useSpring(0)
// We'll add event handling here
return { x, y }
}
The useSpring
hook creates a special type of motion value that animates changes using spring physics. By default, whenever we set a new value, the motion value will animate to that target with a natural spring motion rather than jumping instantly.
Customizing the spring
Let's add some spring configuration to control how the following behavior feels:
const spring = { damping: 3, stiffness: 50, restDelta: 0.001 }
function useFollowPointer(ref) {
const x = useSpring(0, spring)
const y = useSpring(0, spring)
// We'll add event handling here
return { x, y }
}
The spring configuration controls:
damping
: How quickly the spring settles (lower values create more bounce)stiffness
: The strength of the spring (higher values make it more responsive)restDelta
: When to consider the animation complete (smaller values prevent "snapping" at the end of the animation, but make the animation continue for longer)
Adding pointer tracking
Now we need to track the mouse pointer and update our spring values accordingly:
useEffect(() => {
if (!ref.current) return
const handlePointerMove = ({ clientX, clientY }) => {
const element = ref.current
frame.read(() => {
x.set(clientX - element.offsetLeft - element.offsetWidth / 2)
y.set(clientY - element.offsetTop - element.offsetHeight / 2)
})
}
window.addEventListener("pointermove", handlePointerMove)
return () => window.removeEventListener("pointermove", handlePointerMove)
}, [])
This is fairly standard but pay attention to frame.read
. We use this to place the callback on the "read" part of Motion's render loop. This ensures we only update the motion values once per frame, reducing unnecessary work.
Using the motion values
Finally, let's update our component to use our custom hook:
export default function Drag() {
const ref = useRef<HTMLDivElement>(null)
const { x, y } = useFollowPointer(ref)
return <motion.div ref={ref} style={{ ...ball, x, y }} />
}
When we pass our motion values directly to the style
prop, Motion automatically uses them to drive the transforms of the element. As the values update with spring physics, the element will move accordingly.
Conclusion
In this tutorial, we learned how to create a UI element that follows the pointer with natural spring physics. We used:
useSpring
to create motion values that animate changes with spring physicsframe.read()
to efficiently batch DOM reads- Motion's ability to accept motion values directly in the
style
prop
This technique can be used for various interactive UI elements like hover effects, custom cursors, or draggable elements with inertia. By adjusting the spring configuration, you can create different feels - from tight, responsive following to loose, bouncy motion.
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.