score:3

Accepted answer

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/


Related Query

More Query from same tag