# How to Animate SVG Paths and Shapes with Anime.js: A Complete Guide

> Learn to animate SVG paths and shapes with Anime.js using createDrawable, createMotionPath, and morphTo. Master stroke drawing, motion paths, and shape morphing for dynamic web designs.

- Repository: [Julian Garnier/anime](https://github.com/juliangarnier/anime)
- Tags: how-to-guide
- Published: 2026-03-04

---

**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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/src/svg/drawable.js) (lines 60-84), when the `draw` attribute is set with values like `'0 1'` (start end), the proxy computes:

```javascript
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

```javascript
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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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

```javascript
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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/src/svg/morphto.js):

```javascript
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

```javascript
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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/src/svg/motionpath.js) | Generates `translateX`, `translateY`, and `rotate` functions that sample path geometry using `getPathPoint()`. |
| [`src/svg/morphto.js`](https://github.com/juliangarnier/anime/blob/main/src/svg/morphto.js) | Provides shape-morphing logic, sampling points at configurable precision and storing target points via `morphPointsSymbol`. |
| [`src/svg/helpers.js`](https://github.com/juliangarnier/anime/blob/main/src/svg/helpers.js) | Small utilities like `getPath()` that validate SVGGeometryElement instances. |
| [`src/svg/index.js`](https://github.com/juliangarnier/anime/blob/main/src/svg/index.js) | Public re-exports of the three SVG helpers. |
| [`src/index.js`](https://github.com/juliangarnier/anime/blob/main/src/index.js) | Root entry point that exposes the `svg` namespace via `export * as svg from './svg/index.js'`. |
| [`tests/suites/svg.test.js`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/src/svg/drawable.js), [`src/svg/motionpath.js`](https://github.com/juliangarnier/anime/blob/main/src/svg/motionpath.js), and [`src/svg/morphto.js`](https://github.com/juliangarnier/anime/blob/main/src/svg/morphto.js), and exposed through the `svg` namespace in [`src/index.js`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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.