带有圆角的SVG步骤图

问题描述 投票:0回答:1

如何创建带有光滑圆角的阶梯图,如下面的示例所示?

Graph example

角半径取决于台阶之间的坐标差。

我使用d3.js链接并尝试创建自定义SVG曲线,但无法正确实现。

我将不胜感激。也许有一些库吗?

UPD:@exaneta的折线代码

<polyline points="10,40 15,45 30,70 35,75" fill="none" stroke="black" stroke-width="1"></polyline>
javascript html d3.js svg charts
1个回答
0
投票

正如我已经评论过的,您可以使用javascript计算圆角的二次贝塞尔曲线的坐标。贝塞尔曲线的控制点是折线的点。然后,需要获取贝塞尔曲线的起点和终点,并将其作为距折线上控制点距离r的点。一旦有了新路径的所有点,就可以使用它们为dthePath属性建立值。

请确保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>
© www.soinside.com 2019 - 2024. All rights reserved.