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

@technosyr/path2df

v0.2.1

Published

High-performance vector path library with length parameterization, projection, and Bezier curve support

Readme

@technosyr/path2df

High-performance vector path library with length parameterization, Bezier curve support, and point projection.

Features

SVG Path Compatible — full support for SVG path commands (H, V, S, T, A) ✅ Length Parameterization — get points, tangents, and angles by normalized length (0-1) ✅ Real-time Calculation — geometry computed on-the-fly during path construction ✅ Bezier Support — quadratic and cubic curves with precise bounds ✅ Point Projection — project any point onto the path ✅ Path2D Cache — optimized Canvas rendering ✅ TypeScript — full type safety ✅ Zero Dependencies — no external libs required

Installation

npm install @technosyr/path2df

Quick Start

import { VectorPath } from '@technosyr/path2df';

// Create path (API similar to Canvas)
const path = new VectorPath();
path
  .moveTo(0, 0)
  .lineTo(100, 0)
  .bezierCurveTo(150, 0, 150, 50, 150, 100)
  .closePath();

// Length is computed automatically
console.log(path.totalLength); // e.g., 250.5

// Get point at 50% of the path
const midPoint = path.pointAtF(0.5);
console.log(midPoint); // { x: 125, y: 25 }

// Get tangent angle at 75%
const angle = path.angleAtF(0.75);
console.log(angle); // in radians

// Project external point onto path
const proj = path.project({ x: 120, y: 30 });
console.log(proj);
// { f: 0.65, distance: 5.2, point: { x: 118, y: 28 } }

// Render to Canvas
const ctx = canvas.getContext('2d');
ctx.stroke(path.getPath2D());

API

VectorPath

Path Construction (Canvas-compatible)

moveTo(x: number, y: number): this
lineTo(x: number, y: number): this
quadraticCurveTo(cx: number, cy: number, x: number, y: number): this
bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this
closePath(): this
clear(): this

SVG Path Commands

horizontalLineTo(x: number): this
// Horizontal line to (x, currentY) — SVG H command

verticalLineTo(y: number): this
// Vertical line to (currentX, y) — SVG V command

smoothCubicTo(cx2: number, cy2: number, x: number, y: number): this
// Smooth cubic Bezier with automatic first control point — SVG S command

smoothQuadraticTo(x: number, y: number): this
// Smooth quadratic Bezier with automatic control point — SVG T command

arcTo(rx: number, ry: number, rotation: number, largeArc: 0 | 1, sweep: 0 | 1, x: number, y: number): this
// Elliptical arc — SVG A command

Helper Methods

getCurrentPoint(): Vec2 | null
// Get current pen position

getLastControlPoint(): Vec2 | null
// Get last control point (for smooth curves)

Properties

totalLength: number          // Total path length (computed on-the-fly)
bounds: Bounds              // AABB { minX, minY, maxX, maxY }
segmentCount: number        // Number of segments

Parameterization by Length

pointAtF(f: number): Vec2
// Get point at normalized position f ∈ [0, 1]

tangentAtF(f: number): Vec2
// Get tangent vector (not normalized) at position f

angleAtF(f: number): number
// Get tangent angle in radians at position f

segmentAtF(f: number): { segment: ISegment; localT: number; index: number } | null
// Find which segment contains position f

Projection

project(p: Vec2): { f: number; distance: number; point: Vec2 }
// Project point p onto the path
// Returns: normalized position, distance, and closest point

Rendering

getPath2D(): Path2D
// Get cached Path2D for Canvas rendering

Utilities

getSegments(): readonly ISegment[]
// Get all segments

samplePoints(step: number): Generator<Vec2>
// Generate points along the path with given pixel step

Segments

You can also use segments directly:

import { LineSegment, QuadraticSegment, CubicSegment } from '@technosyr/path2df/segments';

const line = new LineSegment(
  { x: 0, y: 0 },
  { x: 100, y: 100 }
);

console.log(line.length);           // 141.42...
console.log(line.pointAt(0.5));     // { x: 50, y: 50 }
console.log(line.tangentAt(0.5));   // { x: 100, y: 100 }

const projection = line.project({ x: 60, y: 40 });
console.log(projection);
// { t: 0.5, d2: 200 }  // t = local parameter, d2 = distance²

Types

interface Vec2 {
  x: number;
  y: number;
}

interface Bounds {
  minX: number;
  minY: number;
  maxX: number;
  maxY: number;
}

interface ISegment {
  readonly length: number;
  readonly start: Vec2;
  readonly end: Vec2;
  readonly bounds: Bounds;

  pointAt(t: number): Vec2;
  tangentAt(t: number): Vec2;
  project(p: Vec2): { t: number; d2: number };
  applyToPath(path: Path2D): void;
}

Use Cases

Animate object along path

const path = new VectorPath()
  .moveTo(0, 0)
  .bezierCurveTo(100, 0, 100, 100, 200, 100);

function animate(time: number) {
  const f = (time % 2000) / 2000; // 0-1 over 2 seconds
  const pos = path.pointAtF(f);
  const angle = path.angleAtF(f);

  // Position and rotate sprite
  sprite.x = pos.x;
  sprite.y = pos.y;
  sprite.rotation = angle;
}

Find closest point on path

function onMouseMove(e: MouseEvent) {
  const mouse = { x: e.clientX, y: e.clientY };
  const proj = path.project(mouse);

  if (proj.distance < 10) {
    console.log('Near path at', proj.point);
    console.log('Progress:', (proj.f * 100).toFixed(1) + '%');
  }
}

Draw evenly spaced markers

const markers = [];
for (let f = 0; f <= 1; f += 0.1) {
  const pos = path.pointAtF(f);
  const angle = path.angleAtF(f);
  markers.push({ pos, angle });
}

markers.forEach(({ pos, angle }) => {
  drawMarker(ctx, pos.x, pos.y, angle);
});

Calculate total path length

// Length is computed automatically during path construction
const path = new VectorPath()
  .moveTo(0, 0)
  .lineTo(100, 0)
  .quadraticCurveTo(150, 50, 100, 100);

console.log('Total length:', path.totalLength.toFixed(2) + 'px');

Performance

  • Segment lengths computed once during construction (no build step needed)
  • Path2D cached and reused for rendering
  • Projection uses grid search + Newton-Raphson refinement
  • No memory allocations in hot paths (pointAtF, tangentAtF)

Browser Support

Requires Path2D support (all modern browsers).

License

MIT

Contributing

PRs welcome! Please open an issue first to discuss changes.

Roadmap

  • [x] SVG path commands (H, V, S, T, A) — v0.2.0
  • [ ] Arc segments optimization
  • [ ] Adaptive LUT for faster queries
  • [ ] Path offsetting (stroke to outline)
  • [ ] Boolean operations
  • [ ] SVG path string parsing
  • [ ] Catmull-Rom splines

Built with ❤️ by TechnoCheese