Highlight Selected Node, Its Links, and Its Children in a D3 Force Directed Graph

Highlight selected node, its links, and its children in a D3 force directed graph

The error is because you are selecting the data objects (d.source and d.target) rather than the DOM elements associated with those data objects.

You've got the line highlighting working, but I would probably combine your code into a single iteration, like this:

 link.style("opacity", function(o) {
return o.source === d || o.target === d ? 1 : opacity;
});

Highlighting the neighboring nodes is harder because what you need to know the neighbors for each node. This information isn't that easy to determine with your current data structures, since all you have as an array of nodes and an array of links. Forget the DOM for a second, and ask yourself how you would determine whether two nodes a and b are neighbors?

function neighboring(a, b) {
// ???
}

An expensive way to do that is to iterate over all of the links and see if there is a link that connects a and b:

function neighboring(a, b) {
return links.some(function(d) {
return (d.source === a && d.target === b)
|| (d.source === b && d.target === a);
});
}

(This assumes that links are undirected. If you only want to highlight forward-connected neighbors, then eliminate the second half of the OR.)

A more efficient way of computing this, if you have to do it frequently, is to have a map or a matrix which allows constant-time lookup to test whether a and b are neighbors. For example:

var linkedByIndex = {};
links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

Now you can say:

function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}

And thus, you can now iterate over the nodes and update their opacity correctly:

node.style("opacity", function(o) {
return neighboring(d, o) ? 1 : opacity;
});

(You may also want to special-case the mouseovered link itself, either by setting a self-link for every node in linkedByIndex, or by testing for d directly when computing the style, or by using a !important css :hover style.)

The last thing I would change in your code is to use fill-opacity and stroke-opacity rather than opacity, because these offer much better performance.

D3js - Force directed graph - advanced highlighting of neigbour nodes and links, is it possible?

To identify your "special" nodes, you could add another attribute to the data that identifies them. Then you can check this in your highlighting function and get second-degree neighbours if necessary. The code would look something like this.

function fade(opacity,color) {
return function(d) {
var connected = [d];
if(d.isAuxiliary) {
node.each(function(o) { if(isConnected(d, o)) { connected.push(o); } });
}
node.style("stroke-opacity", function(o) {
thisOpacity = opacity;
connected.forEach(function(e) {
if(isConnected(e, o)) { thisOpacity = 1; }
});
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
// similar for links
}
}

You can adapt this code to do an arbitrary level of neighbours.

Highlight a node and its neighbour node in force directed graph

This is almost a complete copy and paste from this question, see there for the explanation of the details.

The only things I have changed is to fade the nodes/links out/in with a transition and added connections in both directions to the data structure that is used to determine the neighbours. Complete demo here.

d3js force directed - On hover to node, highlight/colourup linked nodes and links?

The way I solved this problem in my own project was to examine the links to see if their source or target properties matched the hovered node. This should be a step in the right direction.

// On node hover, examine the links to see if their
// source or target properties match the hovered node.
node.on('mouseover', function(d) {
link.style('stroke-width', function(l) {
if (d === l.source || d === l.target)
return 4;
else
return 2;
});
});

// Set the stroke width back to normal when mouse leaves the node.
node.on('mouseout', function() {
link.style('stroke-width', 2);
});

Updated fiddle: http://jsfiddle.net/2pdxz/2/

Highlighting child nodes in D3js v4

The only reason it doesn't work, is because you call your data graph, not json. Change the following line:

var linkedById = {};
json.links.forEach(function(d) {
linkedById[d.source.id + "," + d.target.id] = 1;
});

to

var linkedById = {};
graph.links.forEach(function(d) {
linkedById[d.source.id + "," + d.target.id] = 1;
});

And you'll see that suddently, linkedById gets properly populated, neighbouring nodes are identified correctly, and the highlighting works.

javascript - D3.js force layout highlight without click or hover

I believe you are asking how to trigger your mouseover function when you "mouse over" a node. All you need for this to work is to change your event in your .on(event,function) to "mouseover".

Each node will now trigger your mouseover function when the user's cursor goes over the node.

Your node update section should look like this:

// Enter any new nodes.
node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", "10")
.style("fill", color)
.on("mouseover", mouseover)
.call(force.drag);

See it in action here: Fiddle1

In your comments you say you are looking to change the size of a particular node. I assume you are looking to be able to do this via an event trigger as well.

In the d3-selection documentation for .on it explains that when .on is applied to a node, the triggered function is passed that node's DOM element via the this keyword. (I wanted to add link to documentation but am limited to two links due to rep, I'm sure you can find it or someone else can update this with the link.)

As an example I made two new functions sizeUp and sizeDown that I attached via the "mouseover" and "mouseout" event triggers to each node just like above using d3's .on() function. Each of these functions will either increase or decrease the current node's size by 10px using the this keyword to change the size of the correct DOM element.

Here is the node update section with .on() assignments for "click", "mouseover", and "mouseout"'.

// Enter any new nodes.
node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", "10")
.style("fill", color)
.on("mouseover", sizeUp)
.on("mouseout", sizeDown)
.on("click", mouseover)
.call(force.drag);

And here are the two new functions. In each, the first line retrieves the current size of the node and makes sure it is numeric. The next line updates the "r" attribute of the node by adding or subtracting 10 pixels. Note the use of this as a DOM element for our d3.select() function to retrieve. This way we can access and update the node's DOM attributes using .attr().

function sizeUp(d){
var currentSize = +(d3.select(this).attr("r"));
d3.select(this).attr("r", currentSize + 10);
}

function sizeDown(d){
var currentSize = +(d3.select(this).attr("r"));
d3.select(this).attr("r", currentSize - 10);
}

See this example in action here: Fiddle2

Hopefully this answer has what you are looking for!

How do I highlight/select neighbours of neighbours in D3 force layout?

Been trying for around an hour for this and its a simple change to the code

Change both toggles to - toggle=0;

That way when selecting a node it doesn't clear the selection it just highlights the neighbours



Related Topics



Leave a reply



Submit