Reputation: 11337
I'm using d3.js to create graph with mNode
as nodes and mLink
as links.
In the following code, otherLink
has source
& target
fields which refers to the nodes connected to this link.
otherLink.source
is just an object with the node data, for example:
{"id": 1,
"index: 0,
...
}
How do apply style on this node (look at the // DOESN'T WORK
line below:
function Graph(elementId) {
var svg;
var simulation;
var mNodesData = [];
var mEdgesData = [];
var mNode = null;
var mLink = null;
var elementId;
var heightDelta = 100;
var width = window.innerWidth;
var height = window.innerHeight - heightDelta;
return {
init: function () {
svg = d3.select('#' + elementId)
.append("svg")
.attr("width", width)
.attr("height", height);
simulation = d3.forceSimulation()
.force(".edge", d3.forceLink())
.force("charge", d3.forceManyBody().strength(-600))
.force("center", d3.forceCenter(width / 2, height / 2));
mLink = svg.selectAll(".edge")
.attr("class", "edge")
.style("stroke", LINK_DEFAULT_COLOR)
.style("stroke-width", function (e) {
return 1
/* e.width*/
});
mNode = svg.selectAll(".node")
.attr("class", "node");
},
draw: function () {
mLink = svg.selectAll(".edge")
.data(mEdgesData)
.enter()
.append("line")
.attr("class", "edge")
.style("stroke", LINK_DEFAULT_COLOR)
.style("stroke-width", function (e) {
return 2
/* e.width*/
}).merge(mLink).lower();
mNode = svg.selectAll(".node")
.data(mNodesData)
.enter()
.append("g")
.attr("class", "node").merge(mNode);
mNode.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
mNode.on('mouseover', function (currentNode) {
mLink.filter(function (otherLink) {
if (currentNode !== otherLink.source) {
otherLink.source.style("opacity", BACKGROUND_OPACITY); // DOESN'T WORK
}
return (currentNode !== otherLink.source && currentNode !== otherLink.target);
}).style("opacity", BACKGROUND_OPACITY);
mLink.filter(function (otherLink) {
return (currentNode == otherLink.source || currentNode == otherLink.target);
}).style("opacity", DEFAULT_OPACITY);
});
simulation.nodes(mNodesData);
simulation.force(".edge").links(mEdgesData);
}
}
}
full code: here
Upvotes: 1
Views: 1001
Reputation: 102194
First of all, currentNode
and otherLink.source
in your code are the data of those elements. Therefore, to get the IDs, you have to use their properties. For example, in your conditional:
if (currentNode.id !== otherLink.source.id)
//property here--^----------------------^
If I understand your question correctly, you want to get the ID of the node (or nodes) connected to a given node when you mouseover
it, and then changing the style of that connected node (or any other change you want).
Here is a possible solution. First, on mouseover
, we get the ID of the current node:
mNode.on('mouseover', function(currentNode) {
var thisNodeID = currentNode.id;
Then, we use that ID to populate an array with the ID (or IDs, if more than one) of the connected node (or nodes):
var connectedNodes = mEdgesData.filter(function(d){
return d.source.id === thisNodeID || d.target.id === thisNodeID
}).map(function(d){
return d.source.id === thisNodeID ? d.target.id : d.source.id
});
Finally, we use indexOf
to check what nodes are in that list:
mNode.filter(function(d){
return connectedNodes.indexOf(d.id) > -1
}).style("opacity", DEFAULT_OPACITY);
All together, it would be:
mNode.on('mouseover', function(currentNode) {
var thisNodeID = currentNode.id;
var connectedNodes = mEdgesData.filter(function(d) {
return d.source.id === thisNodeID || d.target.id === thisNodeID
}).map(function(d) {
return d.source.id === thisNodeID ? d.target.id : d.source.id
});
mNode.filter(function(d) {
return connectedNodes.indexOf(d.id) > -1
}).style("opacity", DEFAULT_OPACITY);
});
Since you didn't provide a running code, here is an example of that mouseover
snippet based on a bl.ocks from Mike Bostock, where I'm changing the connected nodes to red: https://bl.ocks.org/anonymous/0db9b4307a1ff6724f89c932f55f6508/2a6cfa3a8bfb03cfa368033faa3804ae5601e403
Upvotes: 1