So i've been working on a collapsible force-directed graph based of the following example.
Im trying to advance from that and add titles to each node. I've followed a similar answer here on stackoverflow, but I cannot implement the solution from that answer into the example above and other similar solutions.
Please can someone point me in the correct direction.
See project code below before implementation.
JS
var w = 600,
h = 600,
radius = 10,
node,
link,
root;
var force = d3.layout.force()
.on("tick", tick)
.charge(function(d) { return -500; })
.linkDistance(function(d) { return d.target._children ? 100 : 50; })
.size([w, h - 160]);
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
root = words[0]; //set root node
root.fixed = true;
root.x = w / 2;
root.y = h / 2 - 80;
update();
function update() {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
// Update the links…
link = svg.selectAll(".link")
.data(links);
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "link")
.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; });
// Exit any old links.
link.exit().remove();
// Update the nodes…
node = svg.selectAll("circle.node")
.data(nodes)
.style("fill", color);
node.transition()
.attr("r", radius);
node.append("title")
.text(function(d) { return d.name; });
// 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", radius)
.style("fill", color)
.on("click", click)
.call(force.drag);
// Exit any old nodes.
node.exit().remove();
}
function tick() {
link.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("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
// Color leaf nodes orange, and packages white or blue.
function color(d) {
if(d._children){
return "#95a5a6";
}else{
switch(d.group) {
case 'r': //adverb
return "#e74c3c";
break;
case 'n': //noun
return "#3498db";
break;
case 'v': //verb
return "#2ecc71";
break;
case 's': //adjective
return "#e78229";
break;
default:
return "#9b59b6";
}
}
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update();
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node.children) node.size = node.children.reduce(function(p, v) { return p + recurse(v); }, 0);
if (!node.id) node.id = ++i;
nodes.push(node);
return node.size;
}
root.size = recurse(root);
return nodes;
}
CSS
circle.node {
cursor: pointer;
stroke: #34495e;
stroke-width: 2px;
box-sizing: border-box;
stroke-location: inside;
}
line.link {
fill: none;
stroke: #34495e;
stroke-width: 1.5px;
}
HTML
<!DOCTYPE html>
<body>
<script src="http://d3js.org/d3.v2.min.js?2.9.6"></script>
<script>
var words = [
{
"group":"n",
"word":"main node",
"children":[
{
"group":"n",
"name":"sub node 1"
},
{
"group":"n",
"name":"sub node 2"
},
{
"group":"n",
"name":"sub node 3"
},
{
"group":"v",
"name":"sub node 4"
},
{
"group":"s",
"name":"sub node 5"
},
{
"group":"s",
"name":"sub node 6"
},
{
"group":"s",
"name":"sub node 7"
},
{
"group":"s",
"name":"sub node 8"
},
{
"group":"s",
"name":"sub node 9"
},
{
"group":"s",
"name":"sub node 10"
},
{
"group":"s",
"name":"sub node 11"
},
{
"group":"r",
"name":"sub node 12",
"children":[
{
"group":"r",
"name":"sub sub node 1"
},
{
"group":"r",
"name":"sub sub node 2"
},
{
"group":"r",
"name":"sub sub node 3"
}
]
}
]
}
]
</script>
</body>
JSFiddle
See Question&Answers more detail:
os