forked from danharr's block: Grid Multi Foci Force Layout
xxxxxxxxxx
<meta charset="utf-8">
<style>
circle {
stroke: #fff;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
// set parameters
var r = 10,
w = $(window).width(),
h = $(window).height(),
width = w-100,
height = h-100,
padding = 6, // separation between nodes
maxRadius = 20,
n = 200, // total number of nodes
m = 8; // number of distinct clusters
// color scale
var color = d3.scale.category10()
.domain(d3.range(m));
// ordinal x scale
var x = d3.scale.ordinal()
.domain(d3.range(m))
.rangePoints([0, width], 1);
// main data
var data = [
{"project":"Thomas Lee-Warren","status":"In Progress","cx":820,"cy":50,"radius":14},
{"project":"Thomas Lee-Warren","status":"Initial Engagement","cx":280,"cy":50,"radius":8},
{"project":"Thomas Lee-Warren","status":"In Progress","cx":820,"cy":50,"radius":18},
{"project":"Peter Bassett","status":"Initial Engagement","cx":280,"cy":170,"radius":5},
{"project":"Peter Bassett","status":"Initial Engagement","cx":280,"cy":170,"radius":10},
{"project":"Nigel Hodges","status":"Suspect","cx":100,"cy":290,"radius":19},
{"project":"Peter Bassett","status":"Suspect","cx":100,"cy":170,"radius":15},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":20},
{"project":"Thomas Lee-Warren","status":"In Progress","cx":820,"cy":50,"radius":14},
{"project":"Unknown","status":"Rejected","cx":1180,"cy":650,"radius":20},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":12},
{"project":"Thomas Lee-Warren","status":"In Progress","cx":820,"cy":50,"radius":20},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":17},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":19},
{"project":"Peter Bassett","status":"Initial Engagement","cx":280,"cy":170,"radius":10},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":10},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":5},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":11},
{"project":"Peter Simmonds","status":"Completed","cx":1000,"cy":530,"radius":15},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":14},
{"project":"Peter Bassett","status":"Initial Engagement","cx":280,"cy":170,"radius":12},
{"project":"Thomas Lee-Warren","status":"Initial Engagement","cx":280,"cy":50,"radius":16},
{"project":"Peter Bassett","status":"In Progress","cx":820,"cy":170,"radius":16},
{"project":"Unknown","status":"Rejected","cx":1180,"cy":650,"radius":19},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":20},
{"project":"Peter Bassett","status":"Suspect","cx":100,"cy":170,"radius":9},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":10},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":17},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":18},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":8},
{"project":"Peter Bassett","status":"Rejected","cx":1180,"cy":170,"radius":6},
{"project":"Peter Bassett","status":"In Progress","cx":820,"cy":170,"radius":17},
{"project":"Peter Bassett","status":"In Progress","cx":820,"cy":170,"radius":10},
{"project":"Peter Bassett","status":"In Progress","cx":820,"cy":170,"radius":5},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":20},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":20},
{"project":"Andy McMurtrie","status":"Qualified ","cx":460,"cy":410,"radius":9},
{"project":"Andy McMurtrie","status":"In Progress","cx":820,"cy":410,"radius":14},
{"project":"Andy McMurtrie","status":"In Progress","cx":820,"cy":410,"radius":14},
{"project":"Andy McMurtrie","status":"Suspect","cx":100,"cy":410,"radius":12},
{"project":"Andy McMurtrie","status":"Funding Sought","cx":640,"cy":410,"radius":12},
{"project":"Thomas Lee-Warren","status":"Qualified ","cx":460,"cy":50,"radius":14},
{"project":"Andy McMurtrie","status":"In Progress","cx":820,"cy":410,"radius":17},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":12},
{"project":"Andy McMurtrie","status":"Funding Sought","cx":640,"cy":410,"radius":10},
{"project":"Nigel Hodges","status":"In Progress","cx":820,"cy":290,"radius":10},
{"project":"Nigel Hodges","status":"Initial Engagement","cx":280,"cy":290,"radius":20},
{"project":"Andy McMurtrie","status":"Initial Engagement","cx":280,"cy":410,"radius":12}
]
// status driven categorical x-axis
var xDomain = ["Suspect","Initial Engagement","Qualified ","Funding Sought","In Progress","Completed","Rejected"];
var xScale = d3.scale.ordinal()
.domain(xDomain)
.rangeBands([50,800]);
// project driven categorical y-axis
var yDomain = ["Thomas Lee-Warren","Peter Bassett","Nigel Hodges","Andy McMurtrie","Peter Simmonds","Unknown"];
var yScale = d3.scale.ordinal()
.domain(yDomain)
.rangeBands([50,800]);
// update data
data.forEach(function(d) {
d.cx = xScale(d.status);
d.cy = yScale(d.project);
});
// setup force layout
var force = d3.layout.force()
.nodes(data)
.size([width, height])
.gravity(0)
.charge(0)
.on("tick", tick)
.start();
// container svg
var svg = d3.select("body").append("svg")
.attr("width", width+80)
.attr("height", height+80);
// draw initial circles
var circle = svg.selectAll("circle")
.data(data)
.enter().append("circle")
// radius
.attr("r", function(d) { return d.radius; })
// fill color
.style("fill", function(d) { return color(d.project); })
// stroke color
.style("stroke","gray")
// stoke width
.style("stroke-width","1px")
// enable drag option
.call(force.drag);
// tick function
function tick(e) {
circle
.each(gravity(.2 * e.alpha))
.each(collide(.5))
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
// move nodes toward cluster focus.
function gravity(alpha) {
return function(d) {
d.y += (d.cy - d.y) * alpha;
d.x += (d.cx - d.x) * alpha;
};
}
// resolve collisions between nodes.
function collide(alpha) {
var quadtree = d3.geom.quadtree(data);
return function(d) {
var r = d.radius + maxRadius + padding,
nx1 = d.x - r,
nx2 = d.x + r,
ny1 = d.y - r,
ny2 = d.y + r;
quadtree.visit(function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== d)) {
var x = d.x - quad.point.x,
y = d.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding;
if (l < r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
});
};
}
circle.append("title").text(function(d) {return d.color ;});
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://code.jquery.com/jquery-1.8.2.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://code.jquery.com/jquery-1.8.2.min.js