SVG粗弯曲路径表现不尽如人意

时间:2015-09-24 10:13:21

标签: d3.js svg sankey-diagram

我在D3中创建一个Sankey图表,使用路径作为粗块连接器来指示流量。但是,我发现路径比它们长期开始时表现得更加粗糙。你可以在这里看到一个例子,我将路径分成几部分:

 image description here

蓝色和橙色重叠,因为蓝色(以及它后面的灰色)不会像更薄的路径一样弯曲,它们会有一种“扭曲”# 34;在他们中间。

除了这些大曲线外,所有线条曲线都能正常工作。我用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&#39;那不会这样做吗?

3 个答案:

答案 0 :(得分:3)

SVG笔划宽度表现不同

问题示例:

enter image description here

<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 curve command调整了2个单位。

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

enter image description here

enter image description here

答案 1 :(得分:3)

虽然Persijn的解决方案很好,但它并不是很完美 - 它与'overaying'细线与下面的扭结线的曲线相匹配。理想情况下,我想完全消除纠结。

正如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;
};

它产生了这个:

enter image description here

选择了这个:

enter image description here

答案 2 :(得分:2)

你的线太粗了,当它跟随贝塞尔曲线时,它会越过线的另一端的起点。

几乎所有非直线贝塞尔曲线都会限制它在开始自相交之前的厚度。你刚刚超过这个限制。如果起点和终点相距较远,则可以稍微厚一些。