Long story short, Konvas path measuring for Path.getLength() and Path.getPointAtLength() methods are broken. The math involved is very complex and its not surprising that there are bugs. But also there’s a simple and higher performance workaround so on balance its not so bad Lets take a look….
Paths can be complex – whether they are route lines on a map, or whatever, they can be constructed of a scary amount of move-to, line-to, Beziers, arcs, etc. Konva supports a subset of SVG path commands and does a good job of drawing them.
Generically, the getPointAtLength() function is intended to be used with the getLength() function. Path.getLength() will give you the total length of the path. You can then chop this up into shorter lengths to get the point on the canvas where each of those lengths end.
For example, if you are drawing movie theatre seating for a reservation app – you need to draw a bunch of seat shapes on a gentle curve. Let’s say on the front row you have to place 10 seats. If you draw the curve as a path you could then get the points at 10 equi-distant positions along the path using
let total = path.getLength();
for (let i = 0; i < 10, i++){
console.log('Seat position ' + i + ' = ' + path.getPointAtLength(i * total / 10))
}
So, Path.getLength() and getPointAtLength() are useful when working with paths – so what’s the workaround to get correct values ?
SVG to the rescue
Browsers have a built-in SVG feature set. Path is a staple of SVG. So we can get the SVG engine to do the math and give us a more accurate getPointAtLength() result.
Here’s a function you can cut & paste to do that job.
function getPosAtLengthPercent(pathData, percent){
// Create an <SVG:path> element to get the path length
// and the various points at a given distance
const pathEle = document.createElementNS("http://www.w3.org/2000/svg", "path");
pathEle.setAttribute("d", pathData);
const totalLength = pathEle.getTotalLength();
const distance = totalLength * percent / 100
return pathEle.getPointAtLength(distance)
}
It should be clear but just in case, what this function does is to create an SVG element, but crucially this is NOT added to the DOM. We set the path data into the SVG path, then get the total path length. Using the input percent parameter, we then compute the distance along the path that this percentage represents, and finally get the position at that point and return it.
Summary
We’ve learned that Konva’s built-in path measuring math is inaccurate, and seen a simple and high-performance workaround.
Thanks for reading.
VW March 2023.
Photo credit Matt Duncan