【问题标题】:JS Canvas: Konva bezier issue [duplicate]JS Canvas:Konva 贝塞尔问题 [重复]
【发布时间】:2020-07-08 02:12:28
【问题描述】:

我想画这样的圆角折线:

将点设置为与Konva library 一致存在问题。

我正在尝试使用bezier 属性来模拟没有张力的平滑拐角,正如文档所说:

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

但如果我设置bezier: true,它只接收 3 对点[x,y] 并忽略点数组的其余部分,然后只切割折线。

Example on codeopen

我不知道如何在没有bezier 选项的情况下仅使用tension 绘制带圆角的直线折线。

有没有办法用 Konva 或其他 JS Canvas 库来实现这样的图形?

【问题讨论】:

标签: javascript canvas konvajs konva


【解决方案1】:

其实有一种方法可以只用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',
      });

使用svg path rules中的二次曲线贝塞尔(Q)算子我们可以得到这样的结果:

这是 Codepen 上的 example

【讨论】:

    【解决方案2】:

    这里是函数的源代码,它可以让你画出漂亮的带有弯角的线条。您可以创建Konva.Line 对象并将特殊的sceneFunc 函数添加到参数中。

    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);
        }
    }
    

    【讨论】:

    • 感谢您的回答。让我在一些代码沙箱中检查一下
    猜你喜欢
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多