Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Forked from mbostock/.block
Last active December 25, 2015 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wboykinm/6955404 to your computer and use it in GitHub Desktop.
Save wboykinm/6955404 to your computer and use it in GitHub Desktop.
linked mouseover starting point

THIS IS THE WORK OF MIKE BOSTOCK! IN ITS ENTIRETY! I'M JUST FIDDLING WITH THE STYLES!

This is a simple example of using CSS class names to support cross-linking between tree elements. Each element in the tree has an associated type field in the data, indicating whether the species is wild or domesticated. (This is bogus data, of course, and only for demonstration purposes.) When you mouseover one of the leaf nodes, other nodes of the same type will highlight.

The coordination happens in two places. First, the G elements for the nodes have a computed class attribute:

.attr("class", function(d) { return "node " + d.type; })

Next, register a mouseover and mouseout handler for interaction:

.on("mouseover", function(d) { highlight(d.type); })
.on("mouseout", function(d) { highlight(null); })

Finally, the highlight function selects nodes by class and toggles an active class which overrides the fill color.

function highlight(type) {
  if (type == null) d3.selectAll(".node").classed("active", false);
  else d3.selectAll(".node." + type).classed("active", true);
}

The active class is defined as:

.node.active {
  fill: red;
}

For more details on how to select related nodes, see my answer to how do you select (and then modify) related elements?

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
fill: none;
stroke: #aaa;
}
.node text {
font: 10px sans-serif;
}
.node circle {
stroke: #fff;
stroke-width: 3px;
}
.node.active {
fill: #0000ff;
stroke: #fff;
cursor:pointer;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 40, right: 40, bottom: 40, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("species.json", function(root) {
var nodes = tree.nodes(root),
links = tree.links(nodes);
// Create the link lines.
svg.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal);
// Create the node circles.
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", function(d) { return "node " + d.type; })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
.on("mouseover", function(d) { highlight(d.type); })
.on("mouseout", function(d) { highlight(null); });
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("x", -6)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return d.name; });
});
function highlight(type) {
if (type == null) d3.selectAll(".node").classed("active", false);
else d3.selectAll(".node." + type).classed("active", true);
}
</script>
{
"name": "Carnivora",
"children": [
{
"name": "Felidae",
"children": [
{
"name": "Felis",
"children": [
{
"name": "catus",
"type": "domesticated"
}
]
},
{
"name": "Panthera",
"children": [
{
"name": "tigris",
"type": "wild"
},
{
"name": "leo",
"type": "wild"
},
{
"name": "onca",
"type": "wild"
},
{
"name": "pardus",
"type": "wild"
}
]
}
]
},
{
"name": "Canidae",
"children": [
{
"name": "Canis",
"children": [
{
"name": "lupus",
"type": "domesticated"
},
{
"name": "latrans",
"type": "wild"
},
{
"name": "aureus",
"type": "wild"
}
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment