3

我在 D3 中创建一个桑基图,使用路径作为粗大的连接器来指示流量。但是,我发现那些比它们更长的路径开始表现得很奇怪。你可以在这里看到一个例子,我将路径分成几个部分:

图片说明在这里

蓝色和橙色重叠,因为蓝色(以及它后面的灰色)的弯曲方式与较细的路径不同,它们有一种“扭结”。

所有的线曲线都很好,除了这些大的。我只用 SVG 做了一个简单的例子:

<SVG height=800 width=800>
<g transform="translate(40,400)">
    <Path class="link1" d="M29,-129C104.5,-129 104.5,-202.125 180,-202.125" />
    <Path class="link2" d="M29,-129C104.5,-129 104.5,-202.125 180,-202.125" />
    <Path class="link3" d="M29,-129C104.5,-129 104.5,-202.125 180,-202.125" />
    <Path class="normal" d="M29,-129 L104.5,-129" />
    <Path class="normal" d="M104.5,-202 L180,-202.125" />
</g>

在这里你可以看到它:

https://jsfiddle.net/hanvyj/t91pbp4w/

我在谷歌上找不到任何东西,我希望有人会遇到这个问题并知道解决方法,或者有更多的 SVG 经验并且知道不会这样做的 'SVG:Path' 的一个很好的替代品?

4

3 回答 3

3

SVG 笔画宽度表现不同

问题示例:

在此处输入图像描述

<svg width="800px" height="600px" viewBox="0 0 100 100">
  <path stroke-width="15" stroke="rgba(0,0,0,0.5)" fill="none" d="m0,40 c 20,0 20,-10 40,-10" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,24 c 5,0 5,-5 10,-5" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,27 c 5,0 5,-2 10,-2" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,30 10,0" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,33 c 5,0 5,2 10,2" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,36 c 5,0 5,5 10,5" />

  <path stroke-width="3" stroke="rgba(255, 200, 50, 0.7)" fill="none" d="m0,46 c 20,0 20,-10 40,-10" />
</svg>

解决方案:

<svg width="800px" height="600px" viewBox="0 0 100 100">
  <path stroke-width="15" stroke="rgba(0,0,0,0.5)" fill="none" d="m0,40 c 20,0 20,-10 40,-10" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,24 c 5,0 5,-5 10,-5" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,27 c 5,0 5,-2 10,-2" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,30 10,0" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,33 c 5,0 5,2 10,2" />
  <path stroke-width="3" stroke="rgba(0,0,0,0.5)" fill="none" D="m40,36 c 5,0 5,5 10,5" />

  <path stroke-width="3" stroke="rgba(255, 200, 50, 0.7)" fill="none" d="m0,46 c 22,0 22,-10 40,-10" />
</svg>

等等,你对路径做了什么?

让我们看看那些橙色路径上的d属性。
问题路径:m0,46 c 20,0 20,-10 40,-10
解决路径:m0,46 c 22,0 22,-10 40,-10

我只是将C 曲线命令调整了2 个单位。

我想要差异的图片......哦,好吧:

在此处输入图像描述

在此处输入图像描述

于 2015-09-24T10:58:16.360 回答
3

虽然 Persijn 的解决方案很好,但它并不十分完美——它使“覆盖”的细线与下面的扭结线的曲线相匹配。理想情况下,我想完全消除扭结。

正如 maioman 建议的那样,对于这种形状,最好我定义完整路径并使用填充,而不是笔触宽度。这给了我更多的控制权。笔划宽度在整个线条长度上保持厚度不变,这不是我真正想要的,正如人们指出的那样,当宽度大于长度时是不可能的。

我希望 x 轴的高度沿其长度保持不变。我创建了一个函数来产生我真正想要的形状,以防万一有人遇到这个:

var linkPath = function(sourceTop,sourceBottom,
                targetTop,targetBottom) {
    //middle
    var MiddleDelta =(targetTop.x - sourceTop.x)/2;
    console.log(MiddleDelta);
    //start in the top left
    var d = "M";
    //top left corner
    d += sourceTop.x + ", " + sourceTop.y + " ";
    d += "C" + (sourceTop.x+MiddleDelta) + "," + sourceTop.y + " ";
    d += (targetTop.x - MiddleDelta) + "," + targetTop.y + " ";
    //top right corner
    d += "" + targetTop.x + "," + targetTop.y + " ";
    //bottom right corner
    d += "L" + targetBottom.x + "," + targetBottom.y + " ";
    d += "C" + (targetBottom.x-MiddleDelta) + "," + targetBottom.y + " ";
    d += (sourceBottom.x + MiddleDelta) + "," + sourceBottom.y + " ";
    //bottom left corner
    d += "" + sourceBottom.x + "," + sourceBottom.y + " ";
    return d;
};

它产生这个:

在此处输入图像描述

与此相反:

在此处输入图像描述

于 2015-09-24T13:14:14.463 回答
2

你的线太粗了,当它沿着贝塞尔曲线时,它会超出线另一端的起点。

几乎任何非直线贝塞尔曲线在开始自相交之前都会限制它的厚度。你刚刚超出了这个限制。如果起点和终点相距较远,您将能够变得更厚一些。

于 2015-09-24T10:52:09.893 回答