除了立方贝塞尔曲线之外,D3.js Sankey图中的链接可以是什么吗?

时间:2018-02-28 01:04:47

标签: javascript d3.js visualization flowchart sankey-diagram

我正在尝试使用Sankey library与D3.js制作能量流图。在我看到的每个example中,节点之间的链接看起来相似并且连续不断。我的理解是Sankey库代码使用D3 Shape库绘制立方贝塞尔曲线。

我想知道是否有任何标准方法可以绘制更复杂的连接链接?

具体来说,我希望这些连接看起来像these flow chartsLawrence Livermore National Lab this diagram创建的an academic article。这两者在曲线之前都具有某种“缓冲”,并且对角线部分看起来彼此平行(或稍微平行)。对于我的情况,如果所有对角线部分都是45度角平行且具有可变大小的缓冲区,我更喜欢。

有没有人对如何做到这一点有任何想法?我是D3.js的新手,非常感谢你有任何帮助或指导!

1 个答案:

答案 0 :(得分:0)

嗯,“标准”方式是D3中的预定义link functions ...但我们可以用任何函数替换那些返回新path定义的方法串。函数的输入是链接对象,它具有源和目标x / y坐标。因此,两者之间的简单直线“路径”可以像这样实现:

function straightLine(d, i) {
    return "M" + d.source.x + "," + d.source.y +
          " L" + d.target.y + "," + d.target.y;
}

用于在svg <path>元素上设置“d”属性,如下所示:

svg.selectAll("path.link")
    .data(mydata)
    .attr("d", straightLine);

对于您的特定情况,构建具有水平开始/结束部分和45°角中间部分的路径,我们使用起点/终点来计算中间交汇点 - 例如:

function angledLine(d, i) {
    var dh = d.target.x - d.source.x; // horizontal distance
    var dv = d.target.y - d.source.y; // vertical distance
    var a1 = d.source.x + (dy - dx)/2; // 1st angle point x
    var a2 = d.target.x - (dy - dx)/2; // 2nd angle point x

    return "M" + d.source.x + "," + d.source.y +
          " L" + a1 + "," + d.source.y + 
          " L" + a2 + "," + d.target.y + 
          " L" + d.target.y + "," + d.target.y;
}

第一个arg d是链接对象。为清楚起见,我正在生成一个相当冗长的路径字符串(具有绝对坐标的连接线)。这样可以正常工作,但可以通过使用“H”和“V”命令水平/垂直移动(或小写版本移动相对距离)来简化。如果要缩短路径字符串(数据较少,但可读性较差),也可以在没有“L”命令的情况下将x,y对串在一起。

  

注意:此实现假定水平距离>垂直距离。我将把它留给OP来确定如何修改另一种情况的路径(改变角度?在角度中间添加一条垂直线?在每一端添加垂直剖面?)   精心设计的链接生成器必须考虑上下左右布局,以及源另一侧的目标(负距离)。但这应该有助于你开始......

第二个arg i是数据数组中链接的索引。尽管在此示例中未使用它,但它可用于向左或向右推动倾斜部分,以帮助避免平行路径中的某些重叠。 YMMV