konvajs / konva

Konva.js is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.
http://konvajs.org/
Other
11.07k stars 896 forks source link

determine length of a line given its points and tension #1738

Closed rrrepos closed 3 months ago

rrrepos commented 3 months ago

Is there a way to determine the length of a line given its points. For example (this shows using react-konva but can be with plain vanilla js too). The challenge increases because of the tension else would have been simple maths.

...
<Line
   x = {50}
   y = {50}
  points = {[0, 0, 25, 25, 50, 0]}
  tension = {0.5} />
...

I see a getLength() method in the Path class but could not figure out how to get a Path from a Line.

Thanks

lavrton commented 3 months ago

I think you can try to generate svg path and pass it into Konva.Path. I didn't test it, but it may be something like this:

// from Konva.Line Source:
function getControlPoints(x0, y0, x1, y1, x2, y2, t) {
  var d01 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)),
    d12 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)),
    fa = (t * d01) / (d01 + d12),
    fb = (t * d12) / (d01 + d12),
    p1x = x1 - fa * (x2 - x0),
    p1y = y1 - fa * (y2 - y0),
    p2x = x1 + fb * (x2 - x0),
    p2y = y1 + fb * (y2 - y0);

  return [p1x, p1y, p2x, p2y];
}

function generateSVGPath(points, tension) {
    let pathData = `M ${points[0]} ${points[1]}`; // Move to start

    for (let i = 2; i < points.length - 2; i += 2) {
        const cp = getControlPoints(
            points[i - 2], points[i - 1],
            points[i], points[i + 1],
            points[i + 2], points[i + 3],
            tension
        );

        // Assuming cp returns four values: [cp1x, cp1y, cp2x, cp2y]
        pathData += ` C ${cp[0]},${cp[1]} ${cp[2]},${cp[3]} ${points[i + 2]},${points[i + 3]}`;
    }

    return pathData;
}

// Example usage:
const points = [0, 0, 25, 25, 50, 0];
const tension = 0.5;
const svgPath = generateSVGPath(points, tension);

const path = new Konva.Path({ data: svgPath });
const length = path.getLenght();
path.destory();
rrrepos commented 3 months ago

@lavrton : Thanks. This works very well. And thanks for creating such a wonderful and friendly library