D3弧形与雪佛龙形端

时间:2016-12-07 16:23:08

标签: javascript d3.js svg shapes svg-path

我使用D3.js绘制了一个arc,默认情况下它具有方形的末端。

var arc = d3.arc()
    .innerRadius(0)
    .outerRadius(100)
    .startAngle(0)
    .endAngle(Math.PI);
d3.selectAll('svg')
    .append('path')
    .attr('d', function() {
        return arc();
    });

如何在其一端绘制一个带有V形的弧形。

Chevron shape

2 个答案:

答案 0 :(得分:6)

我想我明白你在寻找什么,所以我会试一试:

正如您可能从d3.js文档中猜到的那样,d3.arc()没有在一端指出所需的方法。在两端都应用了填充和圆角,我看不出它们如何在两端形成一个点,更不用说一个点了。

我想到了两种解决方案(可能还有很多我甚至无法想到的)

  1. 根据每个圆弧的末端角度丢掉每个圆弧的末端,并附加三角形或其他类似的形状(或者,应用某种蒙版将末端修剪成一个点)
  2. 尝试根据您的需要重新设计d3.arc(),接受以模块化方式开发/改进d3的邀请。
  3. 就个人而言,我认为选项一可能不那么干净,可能更难设计。选项二应该是可行的,并鼓励潜入并制作模块:

      

    小文件很不错,但模块化也使D3更有趣。微型库更容易理解,开发和测试。它们使新人更容易参与并做出贡献。它们减少了“核心模块”和“插件”之间的区别,并加快了D3功能的开发速度。 (https://github.com/d3/d3/blob/master/CHANGES.md

    我以为我会放手一搏。

    我已经尝试了一个基于d3.arc()函数的雪佛龙尖端弧模块的开始尝试。

    d3-shape.js模块中d3.arc()函数的圆角部分可能是最佳显示位置,因为它显示了对弧端的修改。在圆角的情况下,修改弧的模块部分如下所示:

          context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
          context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
          context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
    

    首先处理外边缘(并在上面显示)。第一条线是后角外侧的圆角,第三条线是前方外侧角的圆角。只需移除第三条线即可形成尖角弧(如果从内边缘移除它)。然后剩下的挑战是使弧形的另一端平坦,我通过使用起始角度和内部&外半径找到弧的角,形成一个平端。

    最终结果如下:

    // get tail coordinate (outer)
        var tailOuter = {};
        tailOuter.x = Math.cos(a0) * r1; // a0 = starting angle
        tailOuter.y = Math.sin(a0) * r1; // r1 = outer radius
    
         context.moveTo(tailOuter.x, tailOuter.y);
         context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
    

    我整理了一个快速而脏的module,它接受​​了d3.arc()函数,并创建了一个d3.cheveronArc()函数。这是d3.arc()的内部修改,只有四种方法(inner/outerRadius()start/endAngle())。它无法检查可能导致不良行为的参数(例如:V形臂比弧形长)。它只是一个概念证明,虽然我很高兴看到它是如何寻找一个相当快速的尝试:

    enter image description here

    正如您可能已经注意到的那样,最内圈在其尾部附近有一个奇怪的形状,小的内半径似乎会引起一些类似的问题。

    可以在以下位置查看代码: http://bl.ocks.org/andrew-reid/3375e602cc6c00c4e3ea4799d171ee27

    看着它,我觉得我想添加一个选项,将弧形的倒角添加到弧形的后端以获得更好的视觉效果,但这是一个不同的问题。

答案 1 :(得分:3)

我只想使用带有SVG标记的d3路径生成器。将任何形状添加到任何路径。编辑"结束"通过编辑标记定义。使用D3路径生成器来定义弧(或任何路径)。

值得注意的是,如果你采用这种方法,你必须使用d3路径生成器而不是d3弧生成器,因为弧生成器隐式关闭路径(放置你的" end"标记回到路径的开头)。

在我的例子中,我在开头添加了雪佛龙,以表明它与添加.attr("marker-start","url(#chevron)").attr("marker-end","url(#chevron)")

一样微不足道

D3路径生成器 | https://github.com/d3/d3-path/blob/master/README.md#path

SVG标记 | https://developer.mozilla.org/en-US/docs/Web/SVG/Element/marker

编辑,现在我想起来了,您可以使用d3.symbols为您生成标记/结尾,而不是手动定义形状路径。雪佛龙必须是自定义的,但你可以使用三角形符号。

D3符号 | https://github.com/d3/d3-shape#symbols



console.clear()

var path = d3.path()
path.arc(225,80,70,1,-.5)

var path2 = d3.path()
path2.moveTo(20,20)
path2.bezierCurveTo(150,300,200,0,450,100)

d3.select("svg").append("path")
  .attr("d", path2.toString())
  .attr("stroke","steelblue")
  .attr("fill","none")
  .attr("stroke-width","20")
  .attr("marker-start","url(#chevron)")
  .attr("marker-end","url(#chevron)")

d3.select("svg").append("path")
  .attr("d", path.toString())
  .attr("stroke","#43A2CA")
  .attr("fill","none")
  .attr("stroke-width","20")
  .attr("marker-start","url(#chevron)")
  .attr("marker-end","url(#chevron)")

<script src="https://unpkg.com/d3@4.4.0"></script>
<?xml version="1.0"?>
<svg width="500" height="200" viewBox="0 0 500 200">

  <defs>
    <marker id="chevron"
      viewBox="0 0 20 20" refX="10" refY="10" 
      markerUnits="userSpaceOnUse"
      markerWidth="20" markerHeight="20"
      orient="auto" fill="black">
      <path d="M0 0 10 0 20 10 10 20 0 20 10 10Z" />
    </marker>
  </defs>

</svg>
&#13;
&#13;
&#13;