gsap-offset-path
v1.0.10
Published
GSAP plugin for animating SVG path offsets using Clipper2 WASM
Maintainers
Readme
gsap-offset-path
A GSAP plugin for animating SVG path offsets. Expand or shrink SVG <path> elements smoothly over time — powered by Clipper2 via WebAssembly for precise, production-quality polygon offsetting.
Early stage — This plugin is in active development. The API may change between minor versions. Feedback and issues are welcome.
Install
npm install gsap-offset-pathSetup
import gsap from "gsap";
import { OffsetPathPlugin, initOffsetPath } from "gsap-offset-path";
// Initialize WASM — auto-discovers the files from node_modules
await initOffsetPath();
gsap.registerPlugin(OffsetPathPlugin);That's it. The plugin automatically searches for the WASM files at common paths (including node_modules/gsap-offset-path/wasm/pkg/). If it can't find them, it logs a detailed error to the console telling you exactly what to do.
Custom WASM location
If your setup serves static files from a non-standard location, pass the URLs explicitly:
await initOffsetPath({
wasmUrl: "/assets/clipper_offset_bg.wasm",
glueUrl: "/assets/clipper_offset.js",
});The two WASM files are included in the package at:
node_modules/gsap-offset-path/wasm/pkg/clipper_offset_bg.wasmnode_modules/gsap-offset-path/wasm/pkg/clipper_offset.js
Usage
gsap.to(svgPathElement, {
offsetPath: { offset: -20, originX: 0.5, originY: 1.0 },
duration: 2,
});React example
import { useRef, useEffect, useState } from "react";
import gsap from "gsap";
import { OffsetPathPlugin, initOffsetPath } from "gsap-offset-path";
gsap.registerPlugin(OffsetPathPlugin);
function AnimatedPath() {
const pathRef = useRef<SVGPathElement>(null);
const [ready, setReady] = useState(false);
useEffect(() => {
initOffsetPath().then(() => setReady(true));
}, []);
useEffect(() => {
if (!ready || !pathRef.current) return;
const ctx = gsap.context(() => {
gsap.fromTo(
pathRef.current,
{ offsetPath: { offset: -30, originX: 0.5, originY: 1.0 } },
{ offsetPath: { offset: 0, originX: 0.5, originY: 1.0 }, duration: 2 }
);
});
return () => ctx.revert();
}, [ready]);
return (
<svg viewBox="0 0 200 200">
<path
ref={pathRef}
d="M 50 50 L 150 50 L 150 150 L 50 150 Z"
fill="currentColor"
/>
</svg>
);
}API
initOffsetPath(options?)
Initialize the WASM module. Must be called and awaited before any animations will render. If called with no arguments, the plugin auto-discovers the WASM files.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| wasmUrl | string | (auto-detected) | URL to the .wasm binary |
| glueUrl | string | (auto-detected) | URL to the WASM glue JS file |
isReady()
Returns true if the WASM module has been initialized and is ready.
offsetPath tween property
Use as a GSAP tween property on any SVGPathElement target.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| offset | number | — | Offset in SVG units. Positive = expand outward, negative = shrink inward. |
| joinType | JoinType | Round | How corners are joined at convex vertices. |
| endType | EndType | Polygon | How open path ends are capped. |
| miterLimit | number | 2.0 | Maximum miter distance before a corner falls back to bevel. |
| arcTolerance | number | 0.25 | Curve approximation tolerance for round joins and caps. |
| originX | number | — | Anchor X (0.0 = left, 1.0 = right). Keeps this point fixed during offset. |
| originY | number | — | Anchor Y (0.0 = top, 1.0 = bottom). Keeps this point fixed during offset. |
Shorthand — pass a number directly to set just the offset amount:
gsap.to(path, { offsetPath: -20, duration: 1 });JoinType enum
Controls how adjacent offset edges are connected at convex corners.
| Value | Description |
|-------|-------------|
| JoinType.Round | Arc between the two edge normals (default) |
| JoinType.Miter | Edges extended to a sharp point, capped by miterLimit |
| JoinType.Bevel | Straight cut between the two edge endpoints |
| JoinType.Square | Square cap projected from the corner |
EndType enum
Controls how open path ends are treated.
| Value | Description |
|-------|-------------|
| EndType.Polygon | Treat path as a closed polygon (default) |
| EndType.Joined | Close the path then offset as a filled shape |
| EndType.Butt | Flat end, no cap |
| EndType.Square | Square cap at each end |
| EndType.Round | Round cap at each end |
How it works
On each animation frame GSAP interpolates the offset value and the plugin calls Clipper2 (via WebAssembly) to compute the offset path. The pipeline:
- Parses the original SVG path
dattribute using Lyon (handlesM,L,H,V,C,Q,Zand their relative variants) - Flattens Bezier curves to line segments
- Scales to integer coordinates and normalises winding order
- Runs Clipper2's
ClipperOffsetalgorithm with the configured join and end types - Cleans up self-intersections via polygon union
- Translates the result to keep the anchor point (
originX/originY) fixed - Writes the new path data back to the element
The WASM module is compiled from Rust using clipper2-rust, a port of Angus Johnson's Clipper2 library.
Building the WASM module
If you need to modify the Rust source and rebuild the WASM:
Prerequisites: Rust and wasm-pack
npm run build:wasm # builds and copies WASM files
npm run build # builds the TypeScript pluginLicense
MIT
