Convert and construct SVG path data programmatically.
Pathomorph is a compact utility for generating SVG path strings from geometric primitives and curves. It offers both transformation routines—such as converting rectangles or circles to path data and on the other hand path construction helpers like curved connectors, arrows, and rounded corners.
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<path id="rounded" stroke="#3498db" fill="none" stroke-width="4"/>
<path id="connector" stroke="#e74c3c" fill="none" stroke-width="3"/>
<path id="arrow" stroke="#2ecc71" fill="none" stroke-width="2"/>
</svg>
<script type="module">
import Pathomorph from 'pathomorph';
const p1 = { x: 20, y: 20 };
const p2 = { x: 180, y: 120 };
const from = { x: 30, y: 150 };
const to = { x: 250, y: 50 };
document.getElementById('rounded')
.setAttribute('d', Pathomorph.RoundedRect(p1, p2, 15, 15));
document.getElementById('connector')
.setAttribute('d', Pathomorph.CurvedLine(from, to, 0.4));
document.getElementById('arrow')
.setAttribute('d', Pathomorph.ArrowTip(from, to));
</script>
You can install Pathomorph.js
via npm:
npm install pathomorph
Or with yarn:
yarn add pathomorph
Alternatively, download or clone the repository:
git clone https://github.com/rawify/Pathomorph.js
Include the stewart.min.js
file in your project:
<script src="js/vector2.min.js"></script>
<script src="js/pathomorph.min.js"></script>
<script>
<!-- Access via global `Pathomorph` -->
</script>
Or in a Node.js project:
const Pathomorph = require('pathomorph');
or
import Pathomorph from "pathomorph";
Creates a straight line.
Pathomorph.Line({ x: 0, y: 0 }, { x: 100, y: 0 })
// "M0 0L100 0"
Creates a line shortened on both ends by fixed distances.
- Useful for offsetting lines for arrows or gaps.
- Returns
""
if offsets exceed length.
Pathomorph.LineOffset({ x: 0, y: 0 }, { x: 100, y: 0 }, 10, 10)
// "M10 0L90 0"
Generates a rectangular path between two diagonal points.
Pathomorph.Rectangle({ x: 10, y: 10 }, { x: 60, y: 40 })
// "M10 10L10 40L60 40L60 10z"
Shortcut for Ellipse(center, radius, radius)
. Produces a circular path.
Pathomorph.Circle({ x: 50, y: 50 }, 20)
Draws a full ellipse using two 180° arc segments.
Pathomorph.Ellipse({ x: 60, y: 40 }, 30, 20)
// Draws a full ellipse using two arcs
Draws a circular arc from startAngle
to endAngle
. Handles full circles automatically.
Pathomorph.Arc({ x: 100, y: 100 }, 50, 0, Math.PI)
// Half-circle from 0 to π
Connects a series of points with straight lines.
Pathomorph.Polyline([
{ x: 10, y: 10 },
{ x: 40, y: 20 },
{ x: 80, y: 10 }
])
// "M10 10L40 20L80 10"
Same as Polyline
but closes the shape with a "z"
command.
Pathomorph.Polygon([
{ x: 10, y: 10 },
{ x: 40, y: 20 },
{ x: 80, y: 10 }
])
// "M10 10L40 20L80 10z"
Creates a rectangle with rounded corners. The rounding radii are clamped automatically if too large.
Pathomorph.RoundedRect({ x: 20, y: 20 }, { x: 120, y: 80 }, 10, 10)
Creates a horizontal S-curve between two points using a cubic Bézier.
Pathomorph.CurvedHorizontalLine({ x: 20, y: 50 }, { x: 200, y: 90 })
Same as CurvedHorizontalLine
but curves vertically.
Pathomorph.CurvedVerticalLine({ x: 100, y: 20 }, { x: 120, y: 140 })
Draws a cubic Bézier from a
to b
, with curvature perpendicular to the line direction.
curvature
controls bend magnitude (positive = right-turn from A→B)
Pathomorph.CurvedLine({ x: 30, y: 150 }, { x: 250, y: 50 }, 0.4)
Draws an arrowhead at b
, pointing from a
to b
.
- Returns a closed path suitable for filling.
Pathomorph.ArrowTip({ x: 50, y: 50 }, { x: 100, y: 100 })
// Arrowhead pointing from (50, 50) to (100, 100)
Rounds the corner at B
(where A→B→C forms a bend) with a circular arc of the given radius
, using the mathematically derived method explained here.
Pathomorph.FilletCorner(
{ x: 20, y: 60 },
{ x: 60, y: 60 },
{ x: 60, y: 20 },
10
)
Draws a partial polyline (first fraction
∈ [0,1] of total length).
- Useful for animation or stroke-drawing effects.
Pathomorph.PartialPolyline([
{ x: 0, y: 0 },
{ x: 100, y: 0 },
{ x: 100, y: 100 }
], 0.5)
// Draws the first 50% of the total polyline length
Draws a donut slice (thick circular arc), capped at both ends with rounded edges.
Pathomorph.RingSegment(
{ x: 100, y: 100 },
60,
20,
0,
Math.PI / 2
)
// Quarter ring segment
As every library I publish, Pathomorph.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library.
After cloning the Git repository run:
npm install
npm run build
Copyright (c) 2025, Robert Eisele Licensed under the MIT license.