【问题标题】:D3 Arc With Chevron Shaped End带雪佛龙形末端的 D3 圆弧
【发布时间】:2016-12-07 16:23:08
【问题描述】:

我使用 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();
    });

如何在一端画一个人字形的弧线。

【问题讨论】:

  • SVG 路径可能。您是否要求诸如力导向弧之类的东西,朝着围绕圆圈的一个方向前进?并且末端不是方形的,它们只是平线。
  • 你说的“是什么意思...一端带有人字形的弧线”arc 应该是什么样子的?该弧的结束在哪里,人字形将在哪里绘制。你能写出你想要的视觉效果吗?
  • 你可以放置你想要的确切形状。或者定义你的对象应该是什么样子。

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


【解决方案1】:

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

正如您可能从 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);

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

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

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

看了一下,感觉是想在圆弧的后端加上人字形的倒数的选项,以获得更好的视觉效果,但那是另外一个问题。

【讨论】:

  • 好答案。我认为应该做的唯一调整是不要将点居中,而是确保您正在创建一个等腰三角形。对“圆形箭头”进行图片搜索,所有图片均使用等腰箭头作为其点。
  • 不知道为什么他自己没有提到它(也许只是忘记了这个问题),但这里是 Andrew Reid 的改进版本:bl.ocks.org/Andrew-Reid/51d2665a976266abbaa62eae1ba80cdc 它没有奇尾问题也可以在最后呈现人字形。
  • 您能否建议,如何在 TypeScript 中导入它?
【解决方案2】:

我只会使用 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>

【讨论】:

  • 再看一遍,我真的应该把赏金奖励给你,抱歉。标记是我不知道的一个非常酷的功能。现在我唯一遇到的问题是,为一条路径设置动画,使其看起来正在被绘制并不会同时为标记的位置设置动画。
  • @MuhammadRehanSaeed,别担心,伙计。有时一个问题有多个好的答案,Andrew Reid 制作了一个定制的 d3-chevronArc 来匹配您的确切用例,这真的很酷。如果您最终发布有关动画问题的新问题,请告诉我。
猜你喜欢
  • 2015-08-23
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2015-08-06
  • 2023-03-28
  • 2018-01-22
相关资源
最近更新 更多