score:-1
Complete code from fiddle:
var graph = {"nodes": [
{"name": "Betty", "size": 12, "company": "X", "location": "ChicagoIL"},
{"name": "Frank", "size": 12, "company": "Y", "location": "NewYorkNY"},
{"name": "Jim", "size": 12, "company": "Y", "location": "LosAngelesCA"},
{"name": "Sally", "size": 12, "company": "Z", "location": "TorontoON"},
{"name": "Tom", "size": 12, "company": "X", "location": "ChicagoIL"},
{"name": "GroupA", "size": 18, "company": "T", "location": "x"},
{"name": "GroupB", "size": 18, "company": "T", "location": "x"}],
"links": [
{"source": 2, "target": 5, "bond": 1},
{"source": 3, "target": 5, "bond": 2},
{"source": 4, "target": 5, "bond": 1},
{"source": 0, "target": 6, "bond": 1},
{"source": 1, "target": 6, "bond": 2},
{"source": 4, "target": 6, "bond": 1}],
"locs": [
{"lat": 40.7142, "long": -74.0064, "location": "NewYorkNY"},
{"lat": 34.0522, "long": -118.2428, "location": "LosAngelesCA"},
{"lat": 43.6481, "long": -79.4042, "location": "TorontoON"},
{"lat": 41.8500, "long": -87.6500, "location": "ChicagoIL"}]};
var width = 250;
var height = 250;
var padding = 20;
var color = d3.scale.category20();
var radius = d3.scale.sqrt()
.range([0, 7]);
var scale = d3.scale.linear();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var svg2 = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.size([width, height])
.charge(-400)
.linkStrength(3)
.linkDistance(function(d) {
return radius(d.source.size) + radius(d.target.size) + (30 / (2*d.bond-1))
; });
// network diagram stuff
force
.nodes(graph.nodes)
.links(graph.links)
.on("tick", tick)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("g")
.attr("class", "link");
link.append("line")
.style("stroke-width", function(d) { return (d.bond * 2 - 1) * 3 + "px"; });
link.filter(function(d) { return d.bond > 1; }).append("line")
.attr("class", "separator");
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", function(d) { return "node " + d.name + " " + d.location; })
.call(force.drag)
.on("mouseover", function(d) {
// I would like to insert an if statement to do all of these things to the connected nodes
// if(isConnected(d, o)) {
d3.select(this).select("circle").style("stroke-width", 6);
// Figure out the neighboring node id's with brute strength because the graph is small
var nodeNeighbors = graph.links.filter(function(link) {
// Filter the list of links to only those links that have our target
// node as a source or target
return link.source.index === d.index || link.target.index === d.index;})
.map(function(link) {
// Map the list of links to a simple array of the neighboring indices - this is
// technically not required but makes the code below simpler because we can use
// indexOf instead of iterating and searching ourselves.
return link.source.index === d.index ? link.target.index : link.source.index; });
// Reset all circles - we will do this in mouseout also
svg.selectAll('circle').style('stroke', 'gray');
// now we select the neighboring circles and apply whatever style we want.
// Note that we could also filter a selection of links in this way if we want to
// Highlight those as well
svg.selectAll('circle').filter(function(node) {
// I filter the selection of all circles to only those that hold a node with an
// index in my listg of neighbors
return nodeNeighbors.indexOf(node.index) > -1;
})
.style('stroke', 'orange');
d3.select(this).select("circle").style("stroke", "orange");
d3.select(this).select("text").style("font", "20px sans-serif");
d3.selectAll("rect." + d.location).style("stroke-width", 6);
d3.selectAll("rect." + d.location).style("stroke", "orange");
d3.selectAll("text." + d.location).style("font", "20px sans-serif");
d3.selectAll("tr." + d.name).style("background-color", "orange");
//}
})
.on("mouseout", function(d) {
// if(isConnected(d, o)) {
svg.selectAll('circle').style('stroke', 'gray');
d3.select(this).select("circle").style("stroke-width", 1.5);
//d3.select(this).select("circle").style("stroke", "gray");
d3.select(this).select("text").style("font", "12px sans-serif");
d3.selectAll("rect." + d.location).style("stroke-width", 1.5);
d3.selectAll("rect." + d.location).style("stroke", "gray");
d3.selectAll("text." + d.location).style("font", "12px sans-serif");
d3.selectAll("tr." + d.name).style("background-color", "white");
//}
});
node.append("circle")
.attr("r", function(d) { return radius(d.size); })
.style("fill", function(d) { return color(d.name); });
node.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; });
var linkedByIndex = {};
graph.links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function isConnected(a, b) {
return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index;
}
function tick() {
link.selectAll("line")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
}
// map stuff
var xScale = d3.scale.linear()
.domain([d3.min(graph.locs, function(d) { return d.long; }), d3.max(graph.locs, function(d) { return d.long; })])
.range([padding, width-(4*padding)]);
var yScale = d3.scale.linear()
.domain([d3.min(graph.locs, function(d) { return d.lat; }), d3.max(graph.locs, function(d) { return d.lat; })])
.range([height-padding, padding]);
var mapit = svg2.selectAll(".mapit")
.data(graph.locs)
.enter().append("g")
.on("mouseover", function(d) {
d3.select(this).select("rect").style("stroke-width", 6);
d3.select(this).select("rect").style("stroke", "orange");
d3.select(this).select("text").style("font", "20px sans-serif");
d3.selectAll("g." + d.location + " circle").style("stroke-width", 6);
d3.selectAll("g." + d.location + " circle").style("stroke", "orange");
d3.selectAll("g." + d.location + " text").style("font", "20px sans-serif");
d3.selectAll("tr." + d.location).style("background-color", "orange");
})
.on("mouseout", function(d) {
d3.select(this).select("rect").style("stroke-width", 1.5);
d3.select(this).select("rect").style("stroke", "gray");
d3.select(this).select("text").style("font", "12px sans-serif");
d3.selectAll("g." + d.location + " circle").style("stroke-width", 1.5);
d3.selectAll("g." + d.location + " circle").style("stroke", "gray");
d3.selectAll("g." + d.location + " text").style("font", "12px sans-serif");
d3.selectAll("tr." + d.location).style("background-color", "white");
});
mapit.append("rect")
.attr("x", function(d) { return xScale(d.long); })
.attr("y", function(d) { return yScale(d.lat); })
.attr("height", 20)
.attr("width", 20)
.attr("fill", "gray")
.attr("stroke-width", "1.5")
.attr("stroke", "gray")
.attr("class", function(d) { return d.location ;});
mapit.append("text")
.attr("x", function(d) { return xScale(d.long); })
.attr("y", function(d) { return yScale(d.lat) -5; })
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black")
.text(function(d) { return d.location; })
.attr("class", function(d) { return d.location ;});
// table stuff
function tabulate(tdata, columns) {
var table = d3.select("body").append("table"),
thead = table.append("thead"),
tbody = table.append("tbody");
thead.append("tr").selectAll("th")
.data(columns)
.enter().append("th")
.text(function(column) { return column; });
var rows = tbody.selectAll("tr")
.data(tdata)
.enter().append("tr")
.attr("class", function(d) { return d.name + " " + d.location ;})
.on("mouseover", function(d){
d3.select(this).style("background-color", "orange");
d3.selectAll("g." + d.name + " circle").style("stroke-width", 6);
d3.selectAll("g." + d.name + " circle").style("stroke", "orange");
d3.selectAll("g." + d.name + " text").style("font", "20px sans-serif");
d3.selectAll("rect." + d.location).style("stroke-width", 6);
d3.selectAll("rect." + d.location).style("stroke", "orange");
d3.selectAll("text." + d.location).style("font", "20px sans-serif");
})
.on("mouseout", function(d){
d3.select(this).style("background-color", "white");
d3.selectAll("g." + d.name + " circle").style("stroke-width", 1);
d3.selectAll("g." + d.name + " circle").style("stroke", "gray");
d3.selectAll("g." + d.name + " text").style("font", "12px sans-serif");
d3.selectAll("rect." + d.location).style("stroke-width", 1.5);
d3.selectAll("rect." + d.location).style("stroke", "gray");
d3.selectAll("text." + d.location).style("font", "12px sans-serif");
});
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter().append("td")
.text(function(d) { return d.value; });
return table;
}
var subdata = graph.nodes.filter(function(d) { return d.location!="x"; });
var myTable = tabulate(subdata, ["name", "company", "location"]);
myTable.selectAll("thead th")
.text(function(column) {
return column.charAt(0).toUpperCase() + column.substr(1);
});
myTable.selectAll("tbody tr")
.sort(function(a, b) {
return d3.ascending(a.name, b.name);
});
score:3
I've done something similar by adapting the functions found in this example. The trick is to build selections that work on only the links you'd like to highlight. Here's a snippet of my code:
function linkMouseover(d){
chart.selectAll(".node").classed("active", function(p) { return d3.select(this).classed("active") || p === d.source || p === d.target; });
}
// Highlight the node and connected links on mouseover.
function nodeMouseover(d) {
chart.selectAll(".link").classed("active", function(p) { return d3.select(this).classed("active") || p.source === d || p.target === d; });
chart.selectAll(".link.active").each(function(d){linkMouseover(d)})
d3.select(this).classed("active", true);
}
This force-directed example uses the terminology source and target—I don't imagine there's much distinction between source-target and parent-child. You should be able to make it work by editing the above, such that the .each()
and .classed()
callbacks operate only on the highlighted node, its (multiple generations of) children, and links between them.
Source: stackoverflow.com
Related Query
- D3 highlight selected node, and its links to parent and ancestors in a force directed graph
- Highlight selected node, its links, and its children in a D3 force directed graph
- Highlight a node and its neighbour node in force directed graph
- How to highlight a source node and all its target nodes and corresponding links in d3 hierarchical edge bundling
- D3 force directed layout - changing node color and its links color on button click
- D3 Hive plot highlight Node and its links
- D3 force directed graph with drag and drop support to make selected node position fixed when dropped
- D3 force layout change links into paths and place arrows on node edge instead of center
- D3. How do I act on the selected node and all parent nodes
- Create nodes based on content BBox and get width of source node when adding links in force layout
- D3 force layout shall add nodes and links when clicking a node
- Select node and highlight its connections by feature ID in D3.js
- Add text label to d3 node in Force directed Graph and resize on hover
- Simple graph of nodes and links without using force layout
- d3.js: "Cannot read property 'weight' of undefined" when manually defining both nodes and links for force layout
- D3 force layout: links and nodes --- z-index(?)
- How can I construct a tree using d3 and its force layout?
- How to display and hide links and nodes when clicking on a node in D3 Javascript
- How can I connect two parent node into one child node and how to make a tooltip for each node in the tree pragmatically? in D3 js (SVG)
- How to check d3 js force graph for nodes with no links and remove them?
- D3 force graph rendering nodes and links
- Grouping Circles and Path as a node in D3 Force Layout?
- Speed up d3 force layout with many nodes and links
- How to add a force drag event in D3 and make the node stay where i leave it?
- Select all the paths and parent nodes of a child node in tree layout
- Removing node and its children from d3js tree layout
- how to search a node and highlight it
- Both single and double click on a node in d3 force directed graph
- How to attach nodes and links to simulation force in d3js version 4?
- How to highlight path from root to selected node in d3 js?
More Query from same tag
- how to distinct same keys in first line with d3.csv
- D3 Circle-Packing Clear Labeling Solution
- How to get data on x-axis and number of times occured on y-axis using crossfilter JS?
- ReferenceError : barChartHelper is not defined?
- Update textPath after tween transition in D3
- d3 + google map -- remove data points
- specify color scheme for n number of nodes in networkD3 in R
- Basic D3.js: how to use joins within a function?
- D3.js - Tween Arc position, inner Radius and outer Radius - D3.js Arc
- how to update the markers of a multi line on a brush?
- Accessing nested data in D3
- D3 responsive line chart display no lines
- Fix node position based on another value in d3.js
- Pagination with D3.js
- Position of tree after node expansion
- How to Access Angular Controller Scope from Within Embedded D3 Script
- Using Jquery Mobile to create charts using d3js with fixed width
- Trying to create a map with D3, but it isn't showing up
- Fixing color to each path for donut in d3js
- How increase height dynamically by fixing width of the rect box in d3 js
- D3 multi series line graph
- Converting Observable notebook code to plain Javascript
- nvd3 remove tooltip content for empty points
- D3.js - adding text to nodes in force-directed graph
- d3 Improperly parsing time from timestamp
- Why is my call to selection.join() not returning the enter selection?
- D3 zoomable sunburst not zooming (with data from R)
- Pan/Zoom to specific group ID/getBBox() with d3.behavior.zoom
- data is undefined after importing from a csv file with d3
- d3js v4 - J hoop chart - long stem with a curved arc