如何创建带有光滑圆角的阶梯图,如下面的示例所示?
角半径取决于台阶之间的坐标差。
我使用d3.js链接并尝试创建自定义SVG曲线,但无法正确实现。
我将不胜感激。也许有一些库吗?
UPD:@exaneta的折线代码
<polyline points="10,40 15,45 30,70 35,75" fill="none" stroke="black" stroke-width="1"></polyline>
正如我已经评论过的,您可以使用javascript计算圆角的二次贝塞尔曲线的坐标。贝塞尔曲线的控制点是折线的点。然后,需要获取贝塞尔曲线的起点和终点,并将其作为距折线上控制点距离r
的点。一旦有了新路径的所有点,就可以使用它们为d
的thePath
属性建立值。
请确保r
变量的大小合理。
let polypoints = poly.getAttribute("points");
let r = 5; // distance for the curvature
function getPoints(poly) {
// poly is the polygon's element d attribute
let polyPoints = poly
.replace(/(\r?\n|\r|\t)+/g, "")
.replace(/\-/g, " -")
.split(/[\s,]+/);
polyPoints = removeEmptyElements(polyPoints);
let points = [];
for (let i = 0; i < polyPoints.length; i += 2) {
let temp = [Number(polyPoints[i]), Number(polyPoints[i + 1])];
points.push(temp);
}
return points;
}
function getAngle(c, l) {
let delta_x = l.x - c.x;
let delta_y = l.y - c.y;
let a = Math.atan2(delta_y, delta_x);
return a; //rad;
}
function removeEmptyElements(array) {
for (let i = 0; i < array.length; i++) {
if (array[i] == "") {
array.splice(i, 1);
}
}
return array;
}
function polygonWithRoundedCorners(poly, r) {
let points = getPoints(poly);
let d = `M${points[0][0]},${points[0][1]}`;
for (let i = 1; i < points.length - 1; i++) {
let previous = i - 1;
let next = i + 1;
let c = {};
c.x = points[i][0];
c.y = points[i][1];
let l1 = {};
l1.x = points[previous][0];
l1.y = points[previous][1];
let l2 = {};
l2.x = points[next][0];
l2.y = points[next][1];
let a1 = getAngle(c, l1);
let a2 = getAngle(c, l2);
//if great precision is needed remove .toFixed(3)
let x1 = (c.x + r * Math.cos(a1)).toFixed(3);
let y1 = (c.y + r * Math.sin(a1)).toFixed(3);
let x2 = (c.x + r * Math.cos(a2)).toFixed(3);
let y2 = (c.y + r * Math.sin(a2)).toFixed(3);
d += "L" + x1 + "," + y1 + " Q" + c.x + "," + c.y + " " + x2 + "," + y2;
}
return (d += `L${points[points.length - 1][0]},${
points[points.length - 1][1]
}`);
}
thePath.setAttributeNS(null, "d", polygonWithRoundedCorners(polypoints, r));
svg{border:solid;width:90vh}
<svg viewBox="-5 30 55 55">
<polyline id="poly" points="10,40 15,45 30,70 35,75" fill="none" stroke="black" ></polyline>
<path id="thePath" fill="none" stroke="red" />
</svg>