Gathering detailed insights and metrics for svg-getpointatlength
Gathering detailed insights and metrics for svg-getpointatlength
Gathering detailed insights and metrics for svg-getpointatlength
Gathering detailed insights and metrics for svg-getpointatlength
point-at-length
compute a point from an svg path string
svg-path-properties
Calculate the length for an SVG path, to use it with node or a Canvas element
@liammartens/svg-path-properties
Calculate the length for an SVG path, to use it with node or a Canvas element
svg-path-properties-fork
Calculate the length for an SVG path, to use it with node or a Canvas element
Calculate path lengths, points or angles at lengths based on raw pathdata
npm install svg-getpointatlength
Typescript
Module System
Node Version
NPM Version
75.3
Supply Chain
99
Quality
87.1
Maintenance
100
Vulnerability
100
License
JavaScript (100%)
Total Downloads
2,365
Last Day
1
Last Week
9
Last Month
97
Last Year
1,407
MIT License
10 Stars
84 Commits
3 Forks
1 Watchers
1 Branches
3 Contributors
Updated on Jun 04, 2025
Minified
Minified + Gzipped
Latest Version
1.3.2
Package Id
svg-getpointatlength@1.3.2
Unpacked Size
108.33 kB
Size
25.44 kB
File Count
7
NPM Version
10.2.3
Node Version
20.10.0
Published on
Jun 04, 2025
Cumulative downloads
Total Downloads
Last Day
0%
1
Compared to previous day
Last Week
200%
9
Compared to previous week
Last Month
-6.7%
97
Compared to previous month
Last Year
46.9%
1,407
Compared to previous year
No dependencies detected.
Calculates a path's length or points as well as tangent angles at length based on raw pathdata strings.
This library aims to work as a performant workaround to emulate natively supported browser methods getTotalLength()
and getPointAtLength()
in a non-rendered environment such as node or virtual DOM applications or canvas.
Features: This library provides methods to get:
The provided methods calculate points at lengths by measuring all segments lengths and saving them in a reusable lookup object.
This way you can efficiently calculate hundreds of points on a path without sacrificing too much performance – unlike the quite expensive native getPointAtlength()
method.
Load JS locally or via cdn
<script src="https://cdn.jsdelivr.net/npm/svg-getpointatlength@latest/getPointAtLengthLookup.js"></script>
or (unpkg.com version)
1<script src="https://www.unpkg.com/svg-getpointatlength@latest/getPointAtLengthLookup.js"></script>
or minified version (~ 12KB/6KB gzipped)
<script src="https://cdn.jsdelivr.net/npm/svg-getpointatlength@latest/getPointAtLengthLookup.min.js"></script>
Example: calculate path length from pathData
let d = `M3,7
L13,7
m-20,10
l10,0
V27
H23
v10
h10
C 33,43 38,47 43,47
c 0,5 5,10 10,10
S 63,67 63,67
s -10,10 10,10
Q 50,50 73,57
q 20,-5 0,-10
T 70,40
t 0,-15
A 5, 10 45 1040,20
a5,5 20 01 -10,-10
Z `
// measure path and save metrics in lookup object
let pathLengthLookup = getPathLengthLookup(d)
let totalLength = pathLengthLookup.totalLength
console.log(totalLength)
// point at length
let pt = pathLengthLookup.getPointAtLength(totalLength/2)
console.log(pt)
If you only need to retrieve the total length of a path you can use the simplified helper getPathLengthFromD()
// only length – slightly faster as we don't calculate intermediate lengths
let length = getPathLengthFromD(d)
console.log(length)
npm install svg-getpointatlength
var pathDataLength = require("svg-getpointatlength");
var { getPathLengthLookup, getPathLengthFromD, getPathDataLength, getLength, parsePathDataNormalized } = pathDataLength;
let d = `M3,7
L13,7
m-20,10
l10,0
V27
H23
v10
h10
C 33,43 38,47 43,47
c 0,5 5,10 10,10
S 63,67 63,67
s -10,10 10,10
Q 50,50 73,57
q 20,-5 0,-10
T 70,40
t 0,-15
A 5, 10 45 1040,20
a5,5 20 01 -10,-10
Z `
// measure path and save metrics in lookup object
let pathLengthLookup = getPathLengthLookup(d)
let totalLength = pathLengthLookup.totalLength
console.log(totalLength)
// point at length
let pt = pathLengthLookup.getPointAtLength(totalLength/2)
console.log(pt)
getPathLengthLookup(d)
returns a lookup objects including reusable data about ech path segment as well as the total length.
{
"totalLength": path total length,
"segments": [
{
//lengths calculated between t=0 to t=1 in 36 steps
"lengths": [ length array ],
"points": [ control point array ],
"index": segment index,
"total": segment length,
"type": segment command type (c, q, l, a etc.),
},
//... subsequent segment info
]
}
lookup.pathLengthLookup.getPointAtLength(length, getTangent = false, getSegment = false)
returns an object like this
{x: 10, y:20, index:segmentIndex, t:tValue}
Optionally you can also include tangent angles and segment indices (as well as self contained path data) from the current point-at-length:
method | options/agruments | description | default/values |
---|---|---|---|
getPathLengthLookup(d, precision, onlyLength, getTangent ) | d | A path data string or a already parsed path data array | none |
precision | Specify accuracy for Bézier length calculations. This parameter sets the amount of length intermediate calculations. Default should work even for highly accurate calcuations. Legendre-Gauss approximation is already adaptive | medium , high , low | |
onlyLength | skips the lookup creation and returns only the length of a path | false | |
getTangent | include tangent angles in lookup object (can improve performance) | true | |
getPointAtLength() | length | gets point at specified length | none |
getTangent | include tangent angles in point object (can improve performance) | false | |
getSegment | include segment info in object | false |
// select path
let path = document.querySelector('path')
// get path data attribute
let d = path.getAttribute('d')
// measure path, create lookup
let pathLengthLookup = getPathLengthLookup(d)
// get point, tangent and segment
let length = 100;
let getTangent = true;
let getSegment = true;
let pt = pathLengthLookup.getPointAtLength(length, getTangent, getSegment);
let tangentAngle = pt.angle;
let segmentIndex = pt.index;
let segmentCommand = pt.com;
The returned data object will look like this:
{
// tangent angle in radians
angle: 1.123,
// original command
com: {type: 'A', values: Array(7), p0: {…}},
// original command/segment index
index: 1,
// t value for target length
t: 0.25,
// point coordinates
x: 10,
y: 15,
}
See pointAtLength.html example in demos folder.
So you also have info about the current segment the length is in as well as the t
value used to interpolate the point.
getPathLengthLookup()
now also supports elements these SVGGeometryElements:
<path>
<rect>
<circle>
<ellipse>
<polygon>
<polyline>
<line>
relative units like %
are also supported as long as a viewBox
is provided. Physical units like in
, mm
, pt
, em
are converted to user units pixel based on a 96 dpi resolution.
let path = document.querySelector('path')
// measure path, create lookup
let pathLengthLookup = getPathLengthLookup(path);
// total length
let {totalLength} = pathLengthLookup;
// get point
let pt = pathLengthLookup.getPointAtLength(totalLength/2);
For usage in node.js you need a DOM parser like JSDOM.
To retrieve the path data from an element use getPathDataFromEl(el)
let ellipse = document.querySelector('ellipse');
let pathData = getPathDataFromEl(ellipse);
// measure path, create lookup
let pathLengthLookup = getPathLengthLookup(pathData);
// total length
let {totalLength} = pathLengthLookup;
// get point
let pt = pathLengthLookup.getPointAtLength(totalLength/2);
z
followed by another drawing command than M
– unfortunately valid). See updated demo with "path-from-hell3" (... a pretty good stress test for any path data parser=). Thanks to vboye-foreflight's PR we now get the point at last length whenever the input length exceeds the total length - compliant with native methods' behavior.In case you encounter any problems with the latest versions you can just load a previous one like so:
1<script src="https://www.unpkg.com/svg-getpointatlength@1.0.12/getPointAtLengthLookup.js"></script>
See npm repo for all existing versions
Save path/segment metrics as a reusable lookup for further calculations
d
string to get computable absolute valuest
intervalst
value based on the length difference to get a close length approximationgetPathLengthLookup(d)
accepts stringified path data (as used in d
attributes) or an already parsed path data array as well as an SVGGeometry element.
This library also includes a quite versatile parsing function that could be used separately.
parsePathDataNormalized(d, options)
As length calculations are based on normalized path data values.
All values are converted to absolute and longhand commands.
let options= {
toAbsolute: true, //necessary for most calculations
toLonghands: true, //dito
arcToCubic: false, //sometimes necessary
arcAccuracy: 4, //arc to cubic precision
}
parameter | default | effect |
---|---|---|
toAbsolute | true | convert all to absolute |
toLonghands | true | convert all shorthands to longhands |
arcToCubic | false | convert arcs A commands to cubic béziers |
arcToCubic | 4 | arc to cubic precision – adds more cubic segments to improve length accuracy |
// get original path data: including relative and shorthand commands
let pathData_notNormalized = parsePathDataNormalized(d, {toAbsolute:false, toLonghands:false})
In fact the native browser methods getTotalLength()
and getPointAtlength()
return different results in Firefox, chromium/blink and webkit.
Compared against reproducible/calculable objects/shapes like circles the methods provided by this library actually provide a more accurate result.
Cubic bezier length are approximated using Legendre-Gauss quadrature integral approximation Weights and Abscissae values are adjusted for long path segments.
Elliptical Arc A
commands are approximated also via Legendre-Gauss quadrature (new in version 1.2). Circular arcs are retained which improves speed and accuracy.
Native getPointAtLength()
browser implementations aren't well optimized for recurring point calculations as they start from scratch on each call (parsing, measuring, calculating point at length). To be fair: there is no trivial length calculation algorithm.
Since this library stores all important length data segment by segment – subsequent point (or tangent angle) calculations are way faster than the native methods.
points | native | lookup |
---|---|---|
10 | 2.1 ms | 2.1 ms |
100 | 21.1 ms | 2.2 ms |
1000 | 210 ms | 3.9 ms |
10000 | 2093.6 ms | 6.7 ms |
The lookup creation will usuall take up ~ 1-2ms (depending on the path).
As you can see the lookup's setup overhead is already compensated at 10 iteration.
When we're entering a range of 100 or 1000 points the lookup method clearly wins whereas native getPointAtLength()
severely impacts rendering performance.
polygonFromPathData()
getPointAtLengthLookup_getPolygon.js
includes a helper to generate polygons from path data retaining segemnt final on-path points
<script src="https://cdn.jsdelivr.net/gh/herrstrietzel/svg-getpointatlength@main/getPointAtLengthLookup_getPolygon.js"></script>
let options = {
// target vertice number
vertices: 16,
// round coordinates
decimals: 3,
// retain segment final points: retains shape
adaptive: true,
// return polygon if path has only linetos
retainPoly: true,
// find an adaptive close approximation based on a length difference threshold
tolerance: 0
}
let vertices = polygonFromPathData(pathData, options)
If you found a bug - feel free to file an issue. For debugging you may also test your path with this codepen testbed
(See also demos folder)
No vulnerabilities found.
No security vulnerabilities found.