Path morphing
An example of creating smooth SVG path morphing animations with Motion for React.
Introduction
In this tutorial, we'll explore how to create smooth animations between SVG paths. The Path Morphing example shows how to transform SVG shapes into one another using Motion for React and Flubber.
We'll learn to:
- Using
useMotionValueto track animation progress - Using
useTransformto derive values from the animation progress - Integrating with Flubber for smooth SVG path interpolation
- Creating continuous animations that cycle through multiple paths
Get started
First, let's set up our basic structure. We'll create an SVG container that will hold our morphing shape:
import { useEffect, useState } from "react"
export default function PathMorphing() {
const [pathIndex, setPathIndex] = useState(0)
return (
<svg width="400" height="400">
<g transform="translate(10 10) scale(17 17)">
<path />
</g>
</svg>
)
}
/** Copy path data, paths array and colors array from example source */
We've created a basic SVG with a path element and defined several SVG path strings representing different shapes. We've also set up an array of paths that we'll cycle through and corresponding colors for each shape.
Let's animate!
Import from Motion
Now let's import the necessary functions from Motion and Flubber:
import { interpolate } from "flubber"
import { animate, motion, useMotionValue, useTransform } from "motion/react"
Setting up Motion Values
First, we'll create a Motion Value to track our animation progress:
const progress = useMotionValue(pathIndex)
The useMotionValue hook creates a value that we can animate. We initialize it with the current pathIndex.
Creating derived values
Now, let's use the useTransform hook to derive both our fill color and path data from the progress value:
const fill = useTransform(
progress,
paths.map((_, index) => index),
colors
)
This transforms our progress value into a color based on where we are in the animation. As the progress value changes from 0 to 1, 1 to 2, etc., the fill color will smoothly transition between the corresponding colors in our array.
Path interpolation with Flubber
For the path morphing itself, we'll create a custom hook to handle the interpolation between SVG paths:
function useFlubber(progress, paths) {
return useTransform(progress, paths.map(getIndex), paths, {
mixer: (a, b) => interpolate(a, b, { maxSegmentLength: 0.1 }),
})
}
const path = useFlubber(progress, paths)
This custom hook uses useTransform with a special mixer function that leverages Flubber's interpolate function. The mixer takes two adjacent path strings and returns a function that can generate intermediate path strings based on a progress value.
Animating between paths
Finally, we'll set up an effect to animate between the paths:
useEffect(() => {
const animation = animate(progress, pathIndex, {
duration: 0.8,
ease: "easeInOut",
onComplete: () => {
if (pathIndex === paths.length - 1) {
progress.set(0)
setPathIndex(1)
} else {
setPathIndex(pathIndex + 1)
}
},
})
return () => animation.stop()
}, [pathIndex, progress])
This effect:
- Animates our progress value from its current value to the target
pathIndex - When the animation completes, it updates the
pathIndexto move to the next shape - If we reach the end of our paths array, it resets to the beginning
- Returns a cleanup function that stops the animation if the component unmounts
Connecting to the SVG
Now we need to apply our animated values to the SVG path:
return (
<svg width="400" height="400">
<g transform="translate(10 10) scale(17 17)">
<motion.path fill={fill} d={path} />
</g>
</svg>
)
We replace the static path element with a motion.path and bind our animated values:
- The
fillattribute uses our derived color value - The
dattribute uses our interpolated path data
Conclusion
In this tutorial, we've learned how to create smooth transitions between SVG paths using Motion for React and Flubber. The key techniques we've explored are:
- Using
useMotionValueto create an animation driver - Using
useTransformto derive values from our progress - Using Flubber as a custom mixer to interpolate between SVG paths
- Creating animations that cycle through multiple paths
This technique opens up possibilities for creating engaging UI animations, interactive icons, and creative visual effects in your React applications.
