【问题标题】:D3 Sankey chart using circle node instead of rectangle nodeD3 桑基图使用圆形节点而不是矩形节点
【发布时间】:2014-04-22 00:10:15
【问题描述】:

我想使用Sankey 图表,但使用的是圆形而不是矩形。

我正在学习Mike Bostock的例子。

我通过设置半径更改了那里的代码以使用圆形,但是如何将连接节点的线放置在圆形周围。

任何线索。

谢谢。

【问题讨论】:

  • 分享你的代码会让其他人更容易帮助你。

标签: javascript svg d3.js transformation sankey-diagram


【解决方案1】:

首先,我想告诉你,我喜欢你的想法。

我将引导您完成几个简单的步骤,以获得一个像样的带圆圈的桑基图。最终结果可能不适合您的应用程序,但我想它可能对您有用作为起点。一旦您了解了 d3 Sankey 插件的内部和外部功能,您应该能够准确地构建您设计和希望的内容。


起点

link to jsfiddle

这只是一个基本的 Sankey 示例。我在 jsfiddle 中包含了数据和 Sankey 插件代码。这只是为了方便,因为 jsfiled 没有合适的方法来包含多个文件。所以,这里是:


步骤 1

现在我们将做您已经做过的事情 - 将矩形转换为圆形。

让我们修改这段代码:

// add the rectangles for the nodes
node.append("rect")
    .attr("height", function (d) {
        return d.dy;
    })
    .attr("width", sankey.nodeWidth())

到此代码:

// add the circles for the nodes
node.append("circle")
    .attr("cx", sankey.nodeWidth()/2)
    .attr("cy", function (d) {
        return d.dy/2;
    })
    .attr("r", function (d) {
        return Math.sqrt(d.dy);
    })

我选择使用 Math.sqrt() 因为这样圆的面积将与它所代表的值成比例。我认为这是circle最自然的选择。

结果在这里:


第二步

链接现在异常宽。让它们的宽度与它们所代表的流量的平方根成正比。

让我们修改这段代码:

    .style("stroke-width", function (d) {
        return Math.max(1, d.dy);
    })

到此代码:

    .style("stroke-width", function (d) {
        return Math.max(1, Math.sqrt(d.dy));
    })

结果在这里:


第三步

现在让我们修复链接的端点。

我将使用来自 answer to another SO question 的代码。

这段代码:

var path = sankey.link();

替换为这个:

var path = d3.svg.diagonal()
    .source(function(d) { return {"x":d.source.y, "y":d.source.x}; })            
    .target(function(d) { return {"x":d.target.y, "y":d.target.x}; })
    .projection(function(d) { return [d.y, d.x]; });

结果在这里:


第四步

现在链接节点的链接原点,但我们需要它们来连接我们的圆心

这就是我们要更改此代码的原因:

var path = d3.svg.diagonal()
    .source(function(d) { return {"x":d.source.y, "y":d.source.x}; })            
    .target(function(d) { return {"x":d.target.y, "y":d.target.x}; })
    .projection(function(d) { return [d.y, d.x]; });
    .attr("width", sankey.nodeWidth())

到此代码:

var path = d3.svg.diagonal()
    .source(function(d) {
        return {"x":d.source.y + d.source.dy / 2,
                "y":d.source.x + sankey.nodeWidth()/2};
    })            
    .target(function(d) {
        return {"x":d.target.y + d.target.dy / 2,
                "y":d.target.x + sankey.nodeWidth()/2};
    })
    .projection(function(d) { return [d.y, d.x]; });

结果在这里:

第 5 步

快完成了。在最后一张图中仍然困扰我的是节点标签的位置。如果圆圈更大,它将与其标签重叠。我在最后一个版本中修复了这个问题。结果是:

这里是jsfidle of this final step

【讨论】:

  • 很棒的解释。这正是我一直在寻找的。非常感谢。
  • 非常感谢。完美答案!
  • 解释的很清楚,非常感谢!您所做的这个节点大小减小只有一个小故障:dragmove 仍然根据原始节点大小运行(即约束)。特别是在 node7 上。我试图破解它但没有成功。你对此有什么想法吗?
猜你喜欢
  • 2013-07-25
  • 2013-01-20
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2019-01-19
  • 2010-11-18
相关资源
最近更新 更多