Built with blockbuilder.org
forked from RobinL's block: force directed test
forked from RobinL's block: force directed text fit
forked from RobinL's block: force directed text fit done
forked from RobinL's block: force directed text fit labels
forked from anonymous's block: force directed text fit labels
forked from sunilchandra007's block: force directed text fit labels
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
line {stroke: black}
text {
font: 24px "Helvetica Neue", Helvetica, Arial, sans-serif;
text-anchor: middle;
pointer-events: none;
}
</style>
</head>
<body>
<script>
var height = 500
var width = 500
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + 0 + "," + 0 + ")");
var circle_size = 4;
var colour_scale = d3.scaleOrdinal(d3.schemeCategory10);
function flatten(root) {
var nodes = [],
i = 0;
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!node.id) node.id = ++i;
nodes.push(node);
}
recurse(root);
return nodes;
}
function add_label_leaves(csv_data, root) {
function recurse(tree) {
if (!(tree.children)) {
//add to csv data with correct parent id and uniform size.
new_record = {}
new_record["name"] = tree.data.name + "_label"
new_record["parent"] = tree.data.id
new_record["id"] = tree.data.id + "_label"
new_record["data"] = 20
new_record["text"] = tree.data.text
csv_data.push(new_record)
} else {
_.each(tree.children, function(this_tree) {
recurse(this_tree)
})
}
}
recurse(root)
}
d3.csv("data2.csv", function(csv_data) {
var root_fn = d3.stratify()
.id(function(d) {
return d.id;
})
.parentId(function(d) {
return d.parent;
})
var root = root_fn(csv_data);
//Recurse into root's children, and when we find
var links = root.links()
var nodes = flatten(root)
add_label_leaves(csv_data, root)
var root = root_fn(csv_data)
var links = root.links()
var nodes = flatten(root)
var simulation = d3.forceSimulation(nodes)
.force("link",
d3.forceLink(links)
.distance(function(d) {
//We want the distance to be equal so they are spaced in a circle around the parent
return Math.pow(d.source.data.data, 0.5) * circle_size*1.5;
})
.strength(function(d) {
//Strength just needs to be enough so that length is uniform
return 0.1
})
)
.force("charge", d3.forceManyBody()
.strength(function(d) {
var force = -Math.pow(d.data.data,0.5)*circle_size;
return force})
.distanceMin(0)
.distanceMax(200)
)
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collide", d3.forceCollide(function(d) {return Math.pow(d.data.data,0.5)*circle_size}))
.velocityDecay(0.05)
.alphaMin(0.0001)
.alphaDecay(0.01)
.on("tick", ticked)
function ticked() {
var selection = svg.selectAll(".my_links")
.data(links)
selection.enter()
.append("line")
.attr("class", "my_links")
.merge(selection)
.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;
})
.attr("stroke-width", function(d) {
if (d.target.children) {
return 1
} else {
return 0
}
})
selection.exit().remove();
// Update the nodes…
selection = svg.selectAll(".my_nodes")
.data(nodes, function(d) {
return d.id;
})
//Entering
enterSelection = selection
.enter()
.append("g")
.attr("class", "my_nodes")
circles = enterSelection.append("circle")
rectangles = enterSelection.append("text")
.text(function(d) { return d.data.text; })
.style("font-size", function(d) {
var r = Math.pow(d.data.data, 0.5)*circle_size
return Math.min(2 * r, (2 * r - 8) / this.getComputedTextLength() * 24) + "px"; })
.attr("dy", ".35em")
.style("fill", function(d) {
if (d.children) {
return "white"
} else {
return "black"
}
})
//Update
enterSelection.merge(selection)
.attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")" });
enterSelection.merge(selection).select("circle")
.attr("r", function(d) {
return Math.pow(d.data.data, 0.5)*circle_size;
})
.attr("fill", function(d,i) {
if (d.children) {
return colour_scale(i)
} else {
return "white"
}
})
}
});
</script>
</body>
https://d3js.org/d3.v4.min.js