JS Canvas:Konva 贝塞尔曲线问题
JS Canvas: Konva bezier issue
我想像这样画圆角多段线:
设置点与 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]并忽略点数组的其余部分,然后只切割折线。
我不知道如何在没有 bezier
选项的情况下仅使用 tension
.
绘制带圆角的直线折线
有没有什么方法可以用 Konva 或其他 JS Canvas 库来实现这样的图形?
其实只有用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。
这里是函数的源代码,它可以让你画出漂亮的带弧度的线条。您可以创建 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);
}
}
我想像这样画圆角多段线:
设置点与 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]并忽略点数组的其余部分,然后只切割折线。
我不知道如何在没有 bezier
选项的情况下仅使用 tension
.
有没有什么方法可以用 Konva 或其他 JS Canvas 库来实现这样的图形?
其实只有用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。
这里是函数的源代码,它可以让你画出漂亮的带弧度的线条。您可以创建 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);
}
}