This example shows how to use d3-hexbin for hexagonal binning on a map with the d3.geoAlbersUsa projection. Approximately 3,000 locations of Walmart stores are shown. These are binned into hexagons, and the hexagon area encodes the number of stores that fall into each bin. Color encodes the median age of Walmart stores in that area, with the oldest stores in black and the youngest stores in blue.
<!DOCTYPE html>
<style>
.nation {
fill: #ddd;
}
.states {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
.hexagon {
stroke: #fff;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var parseDate = d3.timeParse("%x");
var color = d3.scaleTime()
.domain([new Date(1962, 0, 1), new Date(2006, 0, 1)])
.range(["black", "steelblue"])
.interpolate(d3.interpolateLab);
var hexbin = d3.hexbin()
.extent([[0, 0], [width, height]])
.radius(10);
var radius = d3.scaleSqrt()
.domain([0, 12])
.range([0, 10]);
// Per https://github.com/topojson/us-atlas
var projection = d3.geoAlbersUsa()
.scale(1280)
.translate([480, 300]);
var path = d3.geoPath();
d3.queue()
.defer(d3.json, "https://d3js.org/us-10m.v1.json")
.defer(d3.tsv, "walmart.tsv", typeWalmart)
.await(ready);
function ready(error, us, walmarts) {
if (error) throw error;
svg.append("path")
.datum(topojson.feature(us, us.objects.nation))
.attr("class", "nation")
.attr("d", path);
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
svg.append("g")
.attr("class", "hexagon")
.selectAll("path")
.data(hexbin(walmarts).sort(function(a, b) { return b.length - a.length; }))
.enter().append("path")
.attr("d", function(d) { return hexbin.hexagon(radius(d.length)); })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("fill", function(d) { return color(d3.median(d, function(d) { return +d.date; })); });
}
function typeWalmart(d) {
var p = projection(d);
d[0] = p[0], d[1] = p[1];
d.date = parseDate(d.date);
return d;
}
</script>