How to Animate SVG Paths and Shapes with Anime.js: A Complete Guide
Anime.js provides a dedicated svg namespace with createDrawable(), createMotionPath(), and morphTo() utilities that enable stroke-drawing animations, motion-path following, and shape morphing by manipulating SVG geometry attributes directly.
Anime.js, the lightweight JavaScript animation library by Julian Garnier, includes a powerful SVG API that simplifies complex vector animations. Whether you need to reveal a logo stroke by stroke, move an element along a curved trajectory, or transform a polygon into a star, the library's specialized svg namespace provides declarative methods to animate SVG paths and shapes with precision.
Understanding the Anime.js SVG API
The SVG functionality is exposed through the svg object imported from animejs. According to the source code in src/index.js, the namespace is exported as export * as svg from './svg/index.js', making three core utilities available:
svg.createDrawable()– Wraps SVG geometry elements to enable a specialdrawattribute that controlsstroke-dasharrayandstroke-dashoffset.svg.createMotionPath()– Generates translation and rotation functions that follow an SVG path's geometry.svg.morphTo()– Calculates interpolation between two compatible SVG shapes for morphing animations.
Drawing and Revealing SVG Shapes with the Drawable Proxy
The drawable proxy is implemented in src/svg/drawable.js. It intercepts calls to setAttribute and maps the custom draw property to stroke-dash calculations, allowing you to animate the revelation of any line, circle, polygon, or path.
How the Drawable Proxy Works
When you invoke svg.createDrawable(selector), the function returns a Proxy that wraps the target SVG element. The proxy uses a normalized path length constant K (set to 1) and calculates the element's scale factor from its Current Transformation Matrix (CTM) to ensure consistent visual dash lengths regardless of transforms.
According to the source in src/svg/drawable.js (lines 60-84), when the draw attribute is set with values like '0 1' (start end), the proxy computes:
const scale = getScaleFactor($scalled);
const os = v1 * -K * scale;
const d1 = (v2 * K * scale) + os;
const d2 = K * scale + ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10 * scale) - d1;
These values are then applied to stroke-dashoffset and stroke-dasharray, creating the drawing effect.
Code Example: Animating Multiple SVG Elements
import { animate, svg } from 'animejs';
// Create drawable proxies for several elements
const drawables = svg.createDrawable([
'#tests line',
'#tests circle',
'#tests polygon',
'#tests polyline',
'#tests rect',
'#tests path'
]);
animate(drawables, {
draw: '0 1', // From 0% to 100% of the path length
ease: 'inOutSine',
translateX: [-100, 0], // Optional extra transform
opacity: 0.5,
duration: 1000
});
Animating Elements Along SVG Paths with Motion Path
The motion path feature, implemented in src/svg/motionpath.js, allows you to make any DOM element follow the geometry of an SVG path while optionally auto-rotating to match the path's tangent.
Creating Motion Path Functions
The svg.createMotionPath(path, offset) function returns an object containing three value functions: translateX, translateY, and rotate. These functions sample the path at the current animation progress using getPathPoint(), which is defined in src/svg/motionpath.js (lines 33-38).
The function signature accepts an optional offset parameter (default 0) that shifts the starting position along the path. As implemented in the source, the offset is added to the progress before sampling: const newProgress = progress + offset * totalLength.
Code Example: Following a Path with Offset
import { animate, svg } from 'animejs';
const ball = document.querySelector('#ball');
const motion = svg.createMotionPath('#myPath', 0.25); // start at 25% of the path
animate(ball, {
...motion, // spreads { translateX, translateY, rotate }
duration: 2000,
easing: 'easeInOutQuad',
autoplay: true
});
Morphing Between SVG Shapes
Shape morphing enables smooth transitions between two compatible SVG geometries (paths, polygons, or polylines). The implementation in src/svg/morphto.js samples points along both shapes and generates intermediate values for the d or points attributes.
The Morphing Algorithm
The svg.morphTo(target, precision) function accepts a target selector or element and a precision value. When precision is provided, the algorithm calculates the maximum length of both paths and samples maxPoints positions along each curve, as shown in src/svg/morphto.js:
const maxPoints = Math.max(Math.ceil(length1 * precision), Math.ceil(length2 * precision));
for (let i = 0; i < maxPoints; i++) {
const t = i / (maxPoints - 1);
const p1 = $path1.getPointAtLength(length1 * t);
const p2 = $path2.getPointAtLength(length2 * t);
// Build path strings...
}
The function returns a two-element array [from, to] that Anime.js uses as the start and end values for the animation. The target points are stored on the source element using a symbol (morphPointsSymbol) for reuse.
Code Example: Polygon to Star Morph
import { animate, svg } from 'animejs';
const shape = document.querySelector('#polygon');
const morph = svg.morphTo('#star', 0.5); // 50% precision (sample more points)
animate(shape, {
d: morph, // For <polygon> the property is `points`; Anime.js normalises it
duration: 1500,
easing: 'easeOutElastic(1, .8)'
});
Key Source Files and Implementation Details
The SVG animation capabilities are modularized under the src/svg/ directory and exposed through the main entry point:
| File | Role |
|---|---|
src/svg/drawable.js |
Implements the proxy that adds the draw attribute and handles dash calculations using the constant K and CTM scale factors. |
src/svg/motionpath.js |
Generates translateX, translateY, and rotate functions that sample path geometry using getPathPoint(). |
src/svg/morphto.js |
Provides shape-morphing logic, sampling points at configurable precision and storing target points via morphPointsSymbol. |
src/svg/helpers.js |
Small utilities like getPath() that validate SVGGeometryElement instances. |
src/svg/index.js |
Public re-exports of the three SVG helpers. |
src/index.js |
Root entry point that exposes the svg namespace via export * as svg from './svg/index.js'. |
tests/suites/svg.test.js |
Test suite demonstrating real-world usage and edge cases like line-cap handling and motion-path offsets. |
Summary
- Drawable Proxy: Use
svg.createDrawable()to wrap SVG elements and animate the specialdrawattribute, which maps tostroke-dasharrayandstroke-dashoffsetfor stroke-reveal effects. - Motion Path: Use
svg.createMotionPath(path, offset)to generate translation and rotation functions that make any element follow an SVG path's geometry, with optional starting offset. - Shape Morphing: Use
svg.morphTo(target, precision)to create smooth transitions between compatible SVG shapes by sampling points along both geometries and interpolating thedorpointsattributes. - Implementation: All features are implemented in
src/svg/drawable.js,src/svg/motionpath.js, andsrc/svg/morphto.js, and exposed through thesvgnamespace insrc/index.js.
Frequently Asked Questions
How do I animate the stroke of an SVG path to draw itself?
Use the svg.createDrawable() method to wrap your SVG element, then animate the draw attribute with values like '0 1' to reveal the stroke from 0% to 100%. The proxy automatically calculates the correct stroke-dasharray and stroke-dashoffset values based on the element's path length and current transformation matrix.
Can I make an element follow an SVG path while rotating to match the curve?
Yes, use svg.createMotionPath(pathSelector, offset) which returns an object containing translateX, translateY, and rotate functions. Spread these into your animate() call, and the element will follow the path's geometry while automatically rotating to align with the path's tangent at each point.
What is the precision parameter in svg.morphTo()?
The precision parameter controls how many points are sampled along the source and target shapes during morphing. A value of 0.5 samples approximately one point per 2 pixels of path length, creating smoother morphs for complex shapes. Higher values increase precision but require more computation. If omitted, the function uses the raw d or points attributes without sampling.
How does Anime.js handle SVG transformations when calculating dash offsets?
The drawable proxy in src/svg/drawable.js computes a scale factor from the element's Current Transformation Matrix (CTM) using getScaleFactor(). This ensures that stroke-dasharray and stroke-dashoffset values are scaled proportionally to any transforms applied to the SVG element, maintaining consistent visual dash lengths regardless of scaling or rotation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →