如何将d3.arc嵌入另一个?

Mar*_*ark 3 geometry d3.js

我试图d3.arc在另一个弧内完美地嵌套生成的弧.

我可以通过"自己动手"来做到这一点:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <script>
    function arc_position(x, y, radius, angle) {
      return {
        x: x + (radius * Math.cos(angle)),
        y: y + (radius * Math.sin(angle))
      };
    }

    function describe_arc(x, y, radius, startAngle, endAngle) {

      var s = arc_position(x, y, radius, endAngle);
      var e = arc_position(x, y, radius, startAngle);

      var sweep = e - s <= 180 ? '0' : '1';

      var d = [
        'M', s.x, s.y,
        'A', radius, radius, 0, sweep, 0, e.x, e.y
      ].join(' ');

      return d;
    }

    var svg = d3.select("body")
      .append("svg")
      .attr("width", 500)
      .attr("height", 500)
      .append("g");
      
    var s = arc_position(250, 250, 200, Math.PI/2);
    var e = arc_position(250, 250, 200, (Math.PI * 3)/2);
      
    svg.append("path")
      .style("fill", "none")
      .style("stroke", "orange")
      .style("stroke-width", "20px")
      .attr("d", describe_arc(250,250,180,(Math.PI * 3)/2, Math.PI/2));
      
    svg.append("path")
      .style("fill", "none")
      .style("stroke", "orange")
      .style("stroke-width", "20px")
      .attr("d", "M" + (s.x + 30) + "," + s.y + "L" + (e.x + 30) + "," + e.y);

    svg.append("path")
      .style("fill", "none")
      .style("stroke", "steelblue")
      .style("stroke-width", "20px")
      .attr("d", describe_arc(250,250,200,(Math.PI * 3)/2, Math.PI/2));
    
    svg.append("path")
      .style("fill", "none")
      .style("stroke", "steelblue")
      .style("stroke-width", "20px")
      .attr("d", "M" + (s.x + 10) + "," + s.y + "L" + (e.x + 10) + "," + e.y);
    
  </script>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚使用的方法d3.arc:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  </head>

  <body>
    <script>
      
      var svg = d3.select("body")
        .append("svg")
        .attr("width", 500)
        .attr("height", 500)
        .append("g")
        .attr("transform","translate(250,250)");
        
      var arc = d3.arc()
        .innerRadius(0)
        .outerRadius(200)
        .startAngle(0)
        .endAngle(Math.PI);

      svg.append("path")
        .style("fill", "none")
        .style("stroke", "steelblue")
        .style("stroke-width", "20px")
        .attr("d", arc());
        
      arc.outerRadius(200 - 40);
      
      svg.append("path")
        .style("fill", "none")
        .style("stroke", "orange")
        .style("stroke-width", "20px")
        .attr("d", arc())
        .attr("transform", "translate(20,0)")
      
    </script>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Pau*_*l S 5

我不认为有一个很好的方法来做这个只是使用d3.arc因为这是用于绘制圆的部分,你试图绘制一个部分椭圆.

您可以使用笔划宽度和内弧的半径生成角度偏移offsetAngle = sin(stroke width / inner radius).弧startAngleoffsetAngle和,endAngleMath.PI - offsetAngle.

不幸的是,这将产生包括圆的中心点的路径.你可以通过L0,0从生成的路径(innerArc().replace("L0,0",""))中删除一些有效的东西,这将给你你想要的东西,虽然是一种丑陋的方式.

因为它是一个相当简单的路径,所以最好使用自己的路径生成器来代替它.

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  </head>

  <body>
    <script>
      
      var svg = d3.select("body")
        .append("svg")
        .attr("width", 500)
        .attr("height", 500)
        .append("g")
        .attr("transform","translate(250,250)");
        
      var outerRadius = 200;
      var stroke = 20;
      var innerRadius = outerRadius - stroke;
      var innerAngle = Math.sin(stroke/innerRadius);

      var outerArc = d3.arc()
        .innerRadius(0)
        .outerRadius(outerRadius)
        .startAngle(0)
        .endAngle(Math.PI);

      var innerArc = d3.arc()
        .innerRadius(0)
        .outerRadius(innerRadius)
        .startAngle(innerAngle)
        .endAngle(Math.PI - innerAngle);

      svg.append("path")
        .style("fill", "none")
        .style("stroke", "steelblue")
        .style("stroke-width", stroke)
        .attr("d", outerArc());
      
      svg.append("path")
        .style("fill", "none")
        .style("stroke", "orange")
        .style("stroke-width", stroke)
        .attr("d", innerArc().replace("L0,0",""));
      
    </script>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)