3

I want to draw polyline with round corners like this:

enter image description here

There is an issue with setting points to line with Konva library.

I am trying to use bezier property to simulate smooth corners without tension and as doc says:

if no tension is provided but bezier=true, we draw the line as a bezier using the passed points

But if I set bezier: true, it receives only 3 pairs of points[x,y] and ignores the rest of point array and then just cuts the polyline.

Example on codeopen

I don't event have an idea how to draw straight polyline with rounded corners without bezier option only with tension.

Is there any approach to implement such figure with Konva or other JS Canvas library?

mr.boris
  • 3,667
  • 8
  • 37
  • 70
  • 2
    Does this answer your question? [How to make rounded-perpendicular lines with react-konva?](https://stackoverflow.com/questions/56095148/how-to-make-rounded-perpendicular-lines-with-react-konva) AFAICS this question covers the same ground. My reading of the answer is that it is same concept as @agershun below - line + quad bez + line + quad bez + line. – Vanquished Wombat Feb 07 '21 at 21:44

2 Answers2

2

Actually, there is a way to draw rounded corners only with Konva.Path:

var path = new Konva.Path({
        x: 20,
        y: 20,
        data: 'm0 0 h 90 q 10 0 10 10 v 80 q 0 10 10 10 h 90',
        stroke: 'red',
      });

Using quadratic curve bezier (Q) operator from svg path rules we can achieve such result:

enter image description here

This is an example on Codepen.

halfer
  • 19,824
  • 17
  • 99
  • 186
mr.boris
  • 3,667
  • 8
  • 37
  • 70
1

Here is the source code of function which allows you to draw pretty nice lines with curved corners. You can create the Konva.Line object and add special sceneFunc function to the parameters.

const BORDER_RADIUS = 40;

let line = new Konva.Line({
    points:[0,0,100,0,100,100,200,100], // put you points array here
    stroke:'#000000',
    strokeWidth:2,
    sceneFunc: function(ctx,shape){
        let points = shape.points();

        ctx.beginPath();
        ctx.moveTo(points[0],points[1]);
        if (points.length == 4) {
            ctx.lineTo(points[2],points[3]);
        } else {
            let n = 0;

            while (n < points.length-4) {
                let deltaX1 = (points[n+2] - points[n+0]);
                let deltaY1 = (points[n+3] - points[n+1]);
                let br1 = Math.min(BORDER_RADIUS,Math.max(Math.abs(deltaX1/2),Math.abs(deltaY1/2)));

                let deltaX2 = (points[n+2+2] - points[n+0+2]);
                let deltaY2 = (points[n+3+2] - points[n+1+2]);
                let br2 = Math.min(BORDER_RADIUS,Math.max(Math.abs(deltaX2/2),Math.abs(deltaY2/2)));

                let br = Math.min(br1,br2);

                let oneX = points[n+0] + (Math.abs(deltaX1) - br)*Math.sign(deltaX1);
                let oneY = points[n+1] + (Math.abs(deltaY1) - br)*Math.sign(deltaY1);

                ctx.lineTo(oneX, oneY);
                n+=2;
                let twoX = points[n+0] + (br)*Math.sign(deltaX2);
                let twoY = points[n+1] + (br)*Math.sign(deltaY2);

                ctx.quadraticCurveTo(points[n+0], points[n+1],twoX, twoY);
            }
            ctx.lineTo(points[points.length-2],points[points.length-1]);        
        }
        ctx.strokeShape(shape);
    }
}
agershun
  • 4,077
  • 38
  • 41