D3动态分层边缘捆绑 - 双向导入

时间:2014-10-02 16:01:00

标签: javascript json svg d3.js bundle-layout

我正在尝试基于M Bostock(http://bl.ocks.org/mbostock/7607999)实现创建动态分层边缘捆绑:

enter image description here

我的数据集的bl.ocks版本在这里:http://bl.ocks.org/ratnakarv/91ace0b5f77fff5ef0ab

与原始节点不同,节点1和节点2之间的关系是一种方式(即节点1可以导入节点2或其他方式),在我的数据集中,节点1和节点2可以有双向导入关系。这在业务流程中经常发生,这是我的应用程序所在的位置。

  • 目前的挑战:

在此示例中 - '评估'导入'创建QOS降级报告'和'创建QOS ...'导入'评估'。但是当鼠标结束时,'评估',节点 - '创建..'显示为红色,但该行为绿色。当鼠标在节点上时 - 'Create ...',导入行和'Assess'显示为红色。

  • 期望要求:

我的要求是,如果存在双向导入,则要么--1。该行以及其他节点以第三种颜色(红色或绿色除外)或2.该行以及其他节点显示为显示为红色。

任何对此的指示都会有所帮助。我对D3有基本的了解,但我不是数据可视化专家,只是尝试在我的工作领域使用可视化来更好地进行沟通。

1 个答案:

答案 0 :(得分:2)

有几种方法可以解决这个问题,但这是我现在能想到的最简单的方法。

请注意,bl.ock中AssessCreate QoS Degradation Report之间的 两个 路径具有相同但相反的值(因为它们都是源彼此的目标)。其中一个恰好放在另一个上面,给它们一个单一路径的外观。这就是为什么这两个节点之间的链接有点锯齿状,而其他节点之间的连接是平滑的。也许我们可以利用这一点。

如果您调整CSS中link--sourcelink--target的定义以使不透明度值小于1,则部分透明的源链接将与部分透明的目标链接重叠,从而呈现一种“新”,不同的颜色。

对于节点颜色,使用“新”颜色创建一个新的CSS类node--both,如果n.sourcen.target中的mousoverednode .classed("node--both", function(n) { return n.source && n.target; }) .classed("node--target", function(n) { return n.target; }) .classed("node--source", function(n) { return n.source; }); 都为真,则将其应用于节点{1}}功能。

links

这并不完美,但这是一个小提琴,展示了这一点:http://jsfiddle.net/w2rfwokx/

关键是要适当地选择源和目标链接颜色和不透明度值(我没有这样做),这样你就可以获得与源链接和目标链接不同的新颜色,也可以使用相同的颜色,无论是否源或目标链接“在顶部”。在当前的小提琴版本中,您可以看到颜色略有不同,具体取决于哪个节点处于活动状态。 This thread或类似的东西可能有所帮助。

您还可以尝试操作links数组,将两个相同的路径合并为一个,并添加一个属性以指示这是一个源 - 目标链接,并在以后处理时使用此属性。

更新:您的评论中有正确的想法。无论如何,颜色技巧更像是黑客攻击。

var unique_links = links.reduce(function(p,c) { var index=p.map(function(d,i) { if(d.source===c.target && d.target===c.source) return i;}).shift(); if(!isNaN(index)) p[index].both=true; else p.push(c); return p; },[]); 数组包含两个项目,用于双向导入节点之间的一条路径。让我们删除其中一个,并在另一个中设置一个属性,以表明这是一个双向导入。

unique_links

现在both=true每个边只有一个元素,而且一个元素有both。我们还将link = link .data(bundle(unique_links)) .enter().append("path") .each(function(d) { d.source = d[0], d.target = d[d.length - 1], d.both = unique_links.filter(function(v) { if (v.source===d.source && v.target===d.target) return v.both; }).shift(); }) .attr("class", "link") .attr("d", line); 属性传递给包布局。

mouseovered

最后一步是更改both函数,使用function mouseovered(d) { node .each(function(n) { n.target = n.source = false; }); link .classed("link--both", function(l) { if((l.target===d || l.source===d) && l.both) return l.source.source = l.source.target = l.target.source = l.target.target = true;}) .classed("link--target", function(l) { if (l.target === d && !l.both) return l.source.source = true; }) .classed("link--source", function(l) { if (l.source === d && !l.both) return l.target.target = true; }) .filter(function(l) { return l.target === d || l.source === d; }) .each(function() { this.parentNode.appendChild(this); }); node .classed("node--both", function(n) { return n.target && n.source; }) .classed("node--target", function(n) { return n.target; }) .classed("node--source", function(n) { return n.source; }); } 设置不同颜色的新CSS类:

mouseouted

并重置function mouseouted(d) { link .classed("link--both", false) .classed("link--target", false) .classed("link--source", false); node .classed("node--both", false) .classed("node--target", false) .classed("node--source", false); } 中的课程:

.link--both {
  stroke: orange;
}

.node--both {
  fill: orange;
}

请记住在CSS中定义新类:

{{1}}

以下是完整代码的更新小提琴:http://jsfiddle.net/w2rfwokx/1/