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 special draw attribute that controls stroke-dasharray and stroke-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 special draw attribute, which maps to stroke-dasharray and stroke-dashoffset for 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 the d or points attributes.
  • Implementation: All features are implemented in src/svg/drawable.js, src/svg/motionpath.js, and src/svg/morphto.js, and exposed through the svg namespace in src/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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →