D3动态分层边缘绑定 - 2路导入 [英] D3 Dynamic hierarchical edge bundling - 2 way import

查看:211
本文介绍了D3动态分层边缘绑定 - 2路导入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个基于M Bostock的动态分层边缘绑定(



与原来的不同,节点1和节点2之间的关系是一种方式(即,节点1可以导入节点2或其他方式),在我的数据集中,节点1和节点2可以具有双向导入关系。




  • 目前的挑战:



在此示例中,'评估'导入'创建QOS降级报告'和'创建QOS ...'还导入'评估'。但是当鼠标结束时,评估,节点 - 创建..显示为红色,但线是绿色的。当鼠标悬停在节点创建...时,导入行以及Assess显示为红色。







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



任何指向这将有所帮助。我有一个基本的D3知识,但我不是一个数据可视化专家,只是尝试使用可视化在我的工作领域更好的沟通。

解决方案

有几种方法可以实现,但这是我现在可以想到的最简单的方法。请注意,评估之间有两个 路径在bl.ock中创建QoS降级报告,它们具有相等但相反的值(因为它们都是源彼此的目标)。其中一个正好放在另一个顶部,给他们一个单一的路径的外观。这就是为什么这两个节点之间的链接有点锯齿,而其他的是平滑的。



如果您调整 link - source link-target 在不透明度值小于1的情况下,部分透明的源链接将重叠部分透明的目标链接,给出一个新的外观,不同颜色。



对于节点颜色,使用new颜色创建一个新的CSS类 node-两者如果 n.source n.target 都为true,则将其应用于节点> mousovered 函数。

 节点
.classed(node - both函数(n){return n.source& n.target;})
.classed(node - target,function(n){return n.target;})
。 classed(node-source,function(n){return n.source;});

这不是完美的,但这里是一个小提琴演示这个: http://jsfiddle.net/w2rfwokx/



关键是选择源和目标链接颜色和不透明度值(我没有这样做),以便您获得与源链接和目标链接不同的新颜色,以及相同的颜色,而不管源链接或目标链接是顶部。在当前的小提琴版本中,您可以看到颜色随着哪个节点活动而略有不同。



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



更新: 您在评论中有正确的想法。



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 。让我们还将两个属性传递到bundle布局。

 链接= 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 函数使用两个:
<$ p> $

 来设置不同颜色的新CSS类> 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 (1){if(l.target === d&!l.both)return l.source.source = true;})
.classed(link - source,function ){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节点 - 目标函数(n){return n.target;})
.classed(node - source,function(n){return n.source;});
}

并重置 mouseouted

  function mouseouted(d){
link
.classed both,false)
.classed(link - target,false)
.classed(link - source,false)

node
.classed(node - both,false)
.classed(node - target,false)
.classed --source,false);
}

请记住在CSS中定义新类:

  .link  - 两者{
stroke:orange;
}

.node - 两者{
fill:orange;
}

这是一个更新的小提琴与完整的代码: http://jsfiddle.net/w2rfwokx/1/


I am trying to create a dynamic hierarchical edge bundling based on M Bostock's (http://bl.ocks.org/mbostock/7607999) implementation:

The bl.ocks version of my data set is here: http://bl.ocks.org/ratnakarv/91ace0b5f77fff5ef0ab

Unlike the original, where a relation between Node 1 and Node 2 is one way (i.e either Node 1 can import Node 2 or other way around), in my data set, Node 1 and Node 2 can have two way import relationship. This happens way too often in business process flows, which is where my application of this is going to be.

  • Current challenge:

In this example- 'Assess' imports 'Create QOS degradation Report' and 'Create QOS...' imports 'Assess' as well. But when mouse is over, 'Assess', node - 'Create..' is shown in red, but the line is green. When mouse is over node- 'Create...', the import line as well as 'Assess' is shown red.

  • Desired Requirement:

My requirement is that if a two way import exists, then either - 1. the line as well as other node be shown in a third colour (other than red or green) or 2. the line as well as other node be shown as red.

Any pointers to this would help. I have a basic knowledge of D3, but I am not a data visualization expert and merely try using visualization in my field of work for better communication.

解决方案

There are a few ways to approach this, but this is the easiest one I can think of as of now.

Note that there are two paths between Assess and Create QoS Degradation Report in your bl.ock with equal but opposite values (as they are both a source and a target for each other). One of them is laid exactly on top the other, giving them the appearance of a single path. That's why the link between these two nodes is somewhat jagged, while the others are smooth. Perhaps we can take advantage of this.

If you adjust the definitions for link--source and link--target in your CSS to have an opacity value of less than 1, a partially transparent source link will overlap a partially transparent target link, giving the appearance of a "new", different color.

As for the node color, create a new CSS class node--both with the "new" color, and apply it to the node if both n.source and n.target are true in the mousovered function.

node
    .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; });

It's not perfect, but here's a fiddle demonstrating this: http://jsfiddle.net/w2rfwokx/

The key is to choose the source and target link colors and opacity values appropriately (which I didn't do) so that you get a new color different enough from the source and target links and also the same color regardless of whether the source or the target link is "on top". In the current fiddle version, you can see that the colors slightly differ depending on which node is active. This thread or something similar might help.

You could also try manipulating the links array to merge the two identical paths into one and adding an attribute to indicate that this is a source-and-target link and use this attribute later while processing.

Update: You have the right idea in your comment. The color trick was more of a hack anyway.

The links array contains two items for the one path between the two-way import nodes. Let's remove one of them and also set an attribute in the other to indicate that this is a two-way import.

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;
 },[]);

Now unique_links has only one element per edge and that one element has both=true. Let's also pass the both attribute along to the bundle layout.

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);

The final step is to change the mouseovered function to set a new CSS class with a different color using 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; });
}

And reset the classes in 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);
}

Remember to define the new classes in CSS:

.link--both {
  stroke: orange;
}

.node--both {
  fill: orange;
}

Here's an updated fiddle with the complete code: http://jsfiddle.net/w2rfwokx/1/

这篇关于D3动态分层边缘绑定 - 2路导入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆