xxxxxxxxxx
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Dorling Cartogram</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3@2.10.3/d3.v2.js"></script>
<style>
#chart {
width: 960px;
height: 470px;
}
circle {
stroke: #000;
stroke-width: .5px;
}
</style>
</head>
<body>
<div id="chart"></div>
<button id="restart" onclick="force.start()">Reheat</button>
<button id="update" onclick="update()">Renew</button>
<script>
var force = d3.layout.force()
.charge(0)
.gravity(0)
.size([960, 470]);
var update;
d3.json("us-state-centroids.json", function(states) {
var project = d3.geo.albersUsa(),
idToNode = {},
links = [];
update = function() {
d3.select("svg").remove();
var svg = d3.select("#chart").append("svg")
.attr("width", 960)
.attr("height", 470)
.append("g")
.attr("transform", "translate(50,20)");
var nodes = states.features.map(function(d) {
var xy = project(d.geometry.coordinates);
return idToNode[d.id] = {
x: xy[0],
y: xy[1],
gravity: {x: xy[0], y: xy[1]},
width: Math.random()*100+25,
height: Math.random()*100+25
};
});
var overlapColor = d3.scale.linear()
.domain([0, 7])
.range(["#2070a0", "orange"])
//nodes = nodes.slice(0, 50)
force
.nodes(nodes)
.links(links)
.start()
.on("tick", function(e) {
var k = e.alpha,
kg = k * .02,
spaceAround = 0.;
nodes.forEach(function(a, i) {
// Apply gravity forces.
a.x += (a.gravity.x - a.x) * kg;
a.y += (a.gravity.y - a.y) * kg;
a.overlapCount = 0;
nodes.slice(i + 1).forEach(function(b) {
/*
// Check for collisions.
var dx = a.x - b.x,
dy = a.y - b.y,
l = Math.sqrt(dx * dx + dy * dy),
d = a.r + b.r;
if (l < d) {
l = (l - d) / l * k;
dx *= l;
dy *= l;
a.x -= dx;
a.y -= dy;
b.x += dx;
b.y += dy;
}
*/
dx = (a.x - b.x)
dy = (a.y - b.y)
adx = Math.abs(dx)
ady = Math.abs(dy)
mdx = (1+spaceAround)* (a.width + b.width)/2
mdy = (1+spaceAround)* (a.height + b.height)/2
if (adx < mdx && ady < mdy) {
l = Math.sqrt(dx * dx + dy * dy)
lx = (adx - mdx) / l * k
ly = (ady - mdy) / l * k
// choose the direction with less overlap
if (lx > ly && ly > 0) lx = 0;
else if (ly > lx && lx > 0) ly = 0;
dx *= lx
dy *= ly
a.x -= dx
a.y -= dy
b.x += dx
b.y += dy
a.overlapCount++;
}
});
});
svg.selectAll("rect")
.style("fill", function(d) { return overlapColor(d.overlapCount); })
.attr("x", function(d) { return d.x- d.width/2; })
.attr("y", function(d) { return d.y- d.height/2; });
svg.selectAll("line")
.attr("x2", function(d) { return d.x; })
.attr("y2", function(d) { return d.y; })
svg.selectAll("circle.end")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
});
var g = svg.selectAll("g")
.data(nodes)
.enter()
.append("g")
.attr("transform", "translate(100,100),scale(0.5)")
g.append("circle")
.attr("stroke", "#000")
.attr("fill", "#fff")
.attr("cx", function(d) { return d.gravity.x; })
.attr("cy", function(d) { return d.gravity.y; })
.attr("r", 3)
g.append("line")
.attr("stroke", "#000")
.attr("opacity", "0.3")
.attr("x1", function(d) { return d.gravity.x; })
.attr("y1", function(d) { return d.gravity.y; })
g.append("rect")
.attr("opacity", 0.75)
.attr("x", function(d) { return d.x - d.width/2; })
.attr("y", function(d) { return d.y - d.height/2; })
.attr("width", function(d, i) { return d.width; })
.attr("height", function(d, i) { return d.height; })
g.append("circle")
.attr("class", "end")
.attr("stroke", "#000")
.attr("fill", "#fff")
.attr("r", 3)
g.append("circle")
};
update();
});
</script>
</body>
</html>
Modified http://mbostock.github.com/d3/d3.v2.js to a secure url
https://mbostock.github.com/d3/d3.v2.js