Svg d3js-两条路径之间的转换

Svg d3js-两条路径之间的转换,svg,d3.js,tween,Svg,D3.js,Tween,我试图用相同的段数在两条路径之间切换。我在这里使用Mike Bostock描述的方法: svg.append(“路径”) .attr(“变换”、“平移(180150)比例(2,2)”) .attr(“d”,d0) .呼叫(转换,d0,d1); 功能转换(路径,d0,d1){ path.transition() .期限(2000年) .attrTween(“d”,pathTween(d1,4)) .each(“end”,function(){d3.select(this).call(transit

我试图用相同的段数在两条路径之间切换。我在这里使用Mike Bostock描述的方法:

svg.append(“路径”)
.attr(“变换”、“平移(180150)比例(2,2)”)
.attr(“d”,d0)
.呼叫(转换,d0,d1);
功能转换(路径,d0,d1){
path.transition()
.期限(2000年)
.attrTween(“d”,pathTween(d1,4))
.each(“end”,function(){d3.select(this).call(transition,d1,d0);});
}
函数路径(d1,精度){
返回函数(){
var path0=这个,
path1=path0.cloneNode(),
n0=path0.getTotalLength(),
n1=(path1.setAttribute(“d”,d1),path1.getTotalLength();
//基于指定精度的距离均匀采样。
变量距离=[0],i=0,dt=precision/Math.max(n0,n1);
当((i+=dt)<1)距离时,推(i);
距离。推(1);
//计算每个距离处的点插值器。
var点=距离。映射(函数(t){
var p0=path0.getPointAtLength(t*n0),
p1=路径1.getPointAtLength(t*n1);
返回d3.插值([p0.x,p0.y],[p1.x,p1.y]);
});
返回函数(t){
返回t<1?“M”+点.map(函数(p){返回p(t);}).join(“L”):d1;
};
};
}
它提供了非常好的结果,但我面临着一个愚蠢的问题。 我想找到一种方法,将第一条路径中的一段与第二条路径中的另一段相关联,以获得更好的粗花呢

例如,此处:2路径具有相似的形状,但粗花呢要比它可能的复杂得多。有办法解决这个问题吗

非常感谢您

您可能找不到任何实用程序/库/等可以为您实现这一点。你会 你必须自己写。或者等别人帮你做。或者付钱给某人

我能想到的解决这个问题的唯一办法是相当乏味的。如果我 如果有时间,我可能会写一个演示并更新这个答案。没有承诺, 不过。事实上,这段代码似乎只对演示中的闭环有用 你链接了

以下是伪代码中的想法。不过,这是相当残忍的暴力

# convert both SVG path `d` attributes from strings to arrays of points
list_1  = convert('#path1')
list_2  = convert('#path2')

min_dist   = 9999
min_pt_set = {}

for each point in list_1 -> (p1)
    for each point in list_2 -> (p2)
        # find the pair of points with the least distance between them
        if (min_dist > dist(p1, p2))
            min_dist = dist(p1, p2)
            min_pt_set = {p1, p2}

# reorder list_1 so that p1 is the first element.
# reorder list_2 so that p2 is the first element.

# convert both lists back into svg path strings

# write the path strings back to the svg `d` attributes.
重新排序后,您可能需要某种形式的方向检查。如果路径 如果在相反方向上定义,则可能需要反转 一条路

我不知道有哪种算法能适用于所有情况。你选择了什么 很可能取决于您编写代码的情况。你至少可以试试 平方和’或仅检查p1和p2附近的点,并求解 最小距离

我希望有人有比我更好的解决方案。这是一个有趣的问题 问题

另请参见:

  • --提到了解析svg路径的方法

  • 此解决方案假定一组点与直线链接(使用路径
    l
    指令),而链接示例也包含曲线(
    c
    指令)。考虑到这一点会使解决方案更加复杂。我在回答中考虑了曲线。根据SVG规范,曲线指定端点。此解决方案既不插值直线也不插值曲线;它只检查端点。如果需要更精确的方法,那么自适应采样可能是一种方法。也许您可以想出如何使用与
    d1
    相同的术语绘制第一条路径
    d0
    。即,使用一系列曲线和直线指定
    d0
    ,这些曲线和直线的顺序与
    d1
    中显示的顺序完全相同,但点的数值不同。由于
    d0
    是一个圆,因此每条直线的终点与前面的曲线的终点相同(即直线的长度为0)。这样,d3可能“知道”如何正确插值。
    # convert both SVG path `d` attributes from strings to arrays of points
    list_1  = convert('#path1')
    list_2  = convert('#path2')
    
    min_dist   = 9999
    min_pt_set = {}
    
    for each point in list_1 -> (p1)
        for each point in list_2 -> (p2)
            # find the pair of points with the least distance between them
            if (min_dist > dist(p1, p2))
                min_dist = dist(p1, p2)
                min_pt_set = {p1, p2}
    
    # reorder list_1 so that p1 is the first element.
    # reorder list_2 so that p2 is the first element.
    
    # convert both lists back into svg path strings
    
    # write the path strings back to the svg `d` attributes.