D3:平移两条相同的路径,使它们 运行 平行

D3: Translating two identical paths so that they run parallel

我的问题如下:

(a) 我在 D3 中绘制了两条坐标完全相同的路径。相同的路径。

(b) 我现在想变换其中一条路径,使它们 运行 平行并且路径之间的 'width' 始终等于 x 像素。我的代码如下:

d3.select("#path2")
.attr("transform", "translate(15,0)");

不幸的是,代码产生以下结果:

如您所见,这些线不平行而是相交。事实上,这有点像狗的早餐。我觉得这可能比听起来要复杂得多。或者是吗?有什么想法吗?

谢谢大家

一种方法是说 'parallel' 路径的每一段都应该与原始路径的相应段平行。因此,对于原件的每一段,您计算一条平行线,给定距离,然后与连续的线相交。您应该始终如一地选择方向,即线段的法线;例如,在每种情况下将法线方向计算为切线方向的 90 度顺时针旋转,或者在每种情况下计算为逆时针旋转。

在很好的情况下——连续线段之间的角度很小,并且与最小线段长度相比距离也很小——这很可能会给你你想要的。在其他情况下,你会弄得一团糟。

我有一个不同的建议方法:创建两条相同的路径,就像您现在正在做的那样。然后,如果您想要一个距离,例如 16px,请将其中一个路径的 stroke-width 设置为大于该距离,并将另一条路径用作 SVG mask,其中 stroke-width 为16,在另一条路径的相同位置。

这样一来,一条路径将在另一条路径中生成 "hollow space",无需任何复杂的数学运算。

这是一个演示。我画圈只是为了表示路径是空心的:

var svg = d3.select("svg")

var dataset = [
    [0, 30],
    [20, 30],
    [50, 55],
    [60, 70],
    [100, 120],
    [110, 90],
    [135, 121],
    [200, 70],
    [300, 130]
];

var line = d3.line()
    .x(function(d) {
        return d[0];
    })
    .y(function(d) {
        return d[1];
    });

svg.append("circle")
    .attr("cx", 200)
    .attr("cy", 70)
    .attr("r", 30)
    .attr("fill", "teal")

var defs = svg.append("defs");

var mask = defs.append("mask")
    .attr("id", "pathMask");

mask.append("rect")
    .attr("width", 300)
    .attr("height", 150)
    .attr("fill", "white");

mask.append("path")
    .attr("d", line(dataset))
    .attr("stroke", "black")
    .attr("fill", "none")
    .attr("stroke-width", 16);

var path = svg.append("path")
    .attr("d", line(dataset))
    .attr("mask", "url(#pathMask)")
    .attr("stroke", "red")
    .attr("stroke-width", 20)
    .attr("fill", "none");
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
</svg>

如果不需要透明填充,解决方案更简单:绘制两条路径,一条覆盖另一条,使用不同的 stroke-width,并填充上面的一条(笔画宽度较小的一条)与背景颜色相同。