npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gsap-offset-path

v1.0.10

Published

GSAP plugin for animating SVG path offsets using Clipper2 WASM

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-path

Setup

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.wasm
  • node_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:

  1. Parses the original SVG path d attribute using Lyon (handles M, L, H, V, C, Q, Z and their relative variants)
  2. Flattens Bezier curves to line segments
  3. Scales to integer coordinates and normalises winding order
  4. Runs Clipper2's ClipperOffset algorithm with the configured join and end types
  5. Cleans up self-intersections via polygon union
  6. Translates the result to keep the anchor point (originX/originY) fixed
  7. 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 plugin

License

MIT