3

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

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

我怎样才能在它的一端画一条带有人字形的弧线。

雪佛龙形状

4

2 回答 2

6

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

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

想到了两个解决方案(可能有很多我什至无法想象)

  1. 根据弧的结束角度,剪掉每条弧的末端,并附加一个三角形或其他类似的形状(或者,应用某种蒙版将末端修剪成一个点)
  2. 尝试根据您的需要重新设计 d3.arc(),接受以模块化方式开发/改进 d3 的邀请。

就个人而言,我认为选项一可能不太干净,而且可能更难设计。选项二应该是可行的,并且在这种鼓励下潜入并制作模块:

小文件很好,但模块化也是为了让 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);

我已经组装了一个快速而肮脏的模块,它采用 d3.arc() 函数并创建一个 d3.cheveronArc() 函数。这是对 d3.arc() 的彻底修改,只有四个方法(inner/outerRadius(), start/endAngle())。它无法检查可能导致不当行为的参数(例如:V 形比弧长)。这只是一个概念证明,尽管我很高兴它看起来是一个相当快速的尝试:

在此处输入图像描述

您可能会注意到,最内圈的尾部附近有一个奇怪的形状,小内半径似乎会导致一些类似的问题。

代码可见:http: //bl.ocks.org/andrew-reid/3375e602cc6c00c4e3ea4799d171ee27

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

于 2016-12-17T03:04:04.857 回答
3

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

值得注意的是,如果您采用这种方法,则必须使用 d3 路径生成器而不是 d3 弧生成器,因为弧生成器会隐式关闭路径(将“结束”标记放回路径的开头)。

在我的示例中,我也在开头添加了 V 形,只是为了表明它与添加.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>

于 2016-12-17T17:57:55.163 回答