SVG 厚曲线路径未按预期运行
SVG thick curved paths not behaving as expected
我正在 D3 中创建一个 Sankey 图,使用路径作为粗大的连接器来指示流程。但是,我发现比它们长的路径更粗的路径开始表现得非常奇怪。你可以在这里看到一个例子,我将路径分成几个部分:
蓝色和橙色重叠,因为蓝色(以及它后面的灰色)不像较细的路径那样弯曲,它们中有一种 "kink"。
所有的直线曲线都很好,除了这些大的曲线。我用 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/
我在 google 上找不到任何东西,我希望有人会遇到这个问题并知道解决方法,或者有更多的 SVG 经验并且知道 'SVG:Path' 的一个很好的替代方案不会这样做?
你的线太粗了,当它沿着贝塞尔曲线时,它超出了线另一端的起点。
几乎所有非直线贝塞尔曲线在开始自相交之前都会限制其厚度。你刚刚超过了这个限制。如果起点和终点相距较远,您可以加厚一点。
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 curve command 调整了 2 个单位。
我想要不同之处的图片...哦哦好吧:
虽然 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;
};
它产生这个:
反对这个:
我正在 D3 中创建一个 Sankey 图,使用路径作为粗大的连接器来指示流程。但是,我发现比它们长的路径更粗的路径开始表现得非常奇怪。你可以在这里看到一个例子,我将路径分成几个部分:
蓝色和橙色重叠,因为蓝色(以及它后面的灰色)不像较细的路径那样弯曲,它们中有一种 "kink"。
所有的直线曲线都很好,除了这些大的曲线。我用 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/
我在 google 上找不到任何东西,我希望有人会遇到这个问题并知道解决方法,或者有更多的 SVG 经验并且知道 'SVG:Path' 的一个很好的替代方案不会这样做?
你的线太粗了,当它沿着贝塞尔曲线时,它超出了线另一端的起点。
几乎所有非直线贝塞尔曲线在开始自相交之前都会限制其厚度。你刚刚超过了这个限制。如果起点和终点相距较远,您可以加厚一点。
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 curve command 调整了 2 个单位。
我想要不同之处的图片...哦哦好吧:
虽然 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;
};
它产生这个:
反对这个: