An adaptation of the NPR hexgrid that sets hexagon size in play as a thematic variable.
Still needs a legend, but:
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<style>
body { background-color: #fff; }
</style>
<svg id="cartogram" width="800" height="500"></svg>
<script>
// The svg
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
// Map and projection
var projection = d3.geoMercator()
.scale(600) // This is the zoom
.translate([1500, 750]); // You have to play with these values to center your map
// Path generator
var path = d3.geoPath()
.projection(projection)
// Colors
var lowColor = '#ffffff'
var highColor = '#bc2a66'
// load in the data
d3.queue()
.defer(d3.json, "us_states_hexgrid.geojson")
.defer(d3.csv, "sn.csv")
.await(ready);
function ready(error, geo, sn) {
if (error) throw error;
// get min/max of everything
var getArray = function(data,name) {
var dataArray = [];
for (var d = 0; d < data.length; d++) {
dataArray.push(parseInt(data[d][name]))
}
return dataArray
}
var min1 = d3.min(getArray(sn,'population'))
var max1 = d3.max(getArray(sn,'population'))
var min2 = d3.min(getArray(sn,'avg_sn'))
var max2 = d3.max(getArray(sn,'avg_sn'))
// create color scale
var colorRamp = d3.scaleSqrt()
.domain([min2,max2])
.range([lowColor,highColor])
// Join geojson and CSV (gotta be a better way of doing this)
for (var i = 0; i < sn.length; i++) {
// Grab State Name
var dataState = sn[i].state;
// Grab grouped record count
var dataPop = sn[i].population;
var dataSn = sn[i].avg_sn
// Find the corresponding state inside the GeoJSON
for (var j = 0; j < geo.features.length; j++) {
var geoState = geo.features[j].properties.abbrv;
if (dataState == geoState) {
// Copy the data value into the JSON
geo.features[j].properties.population = parseInt(dataPop);
geo.features[j].properties.avg_sn = parseInt(dataSn);
// Stop looking through the JSON
break;
}
}
}
// Draw the scaled features
svg.append("g")
.selectAll("path")
.data(geo.features)
.enter()
.append("path")
.attr("fill", function(d) { return colorRamp(d.properties.avg_sn) || 'rgba(255,255,255,0.2)' })
.attr("d", path)
.attr("stroke", "rgba(100,100,100,0.9)")
// create resize scale (via //bl.ocks.org/rveciana/5928736)
.attr("transform", function(d) {
scale_factor = Math.sqrt(d.properties.population/(max1-min1));
var centroid = path.centroid(d),
x = centroid[0],
y = centroid[1];
return "translate(" + x + "," + y + ")"
+ "scale(" + scale_factor + ")"
+ "translate(" + -x + "," + -y + ")";
});
// Draw the mesh
svg.append("g")
.selectAll("path")
.data(geo.features)
.enter()
.append("path")
.attr("fill", "none")
.attr("d", path)
//.attr("stroke", "rgba(50,50,50,0.2)")
// Add the labels
svg.append("g")
.selectAll("labels")
.data(geo.features)
.enter()
.append("text")
.attr("x", function(d){return path.centroid(d)[0]})
.attr("y", function(d){return path.centroid(d)[1]})
.text(function(d){ return d.properties.abbrv})
.attr("text-anchor", "middle")
.attr("alignment-baseline", "central")
.style("font-size", 11)
.style("fill", "rgba(25,25,25,0.6)")
.attr("transform","translate(0,-15)")
}
</script>
id,state,population,avg_sn
2,AK,733375,
1,AL,4830620,72
5,AR,2958208,65
4,AZ,6641928,89
6,CA,38421464,83
8,CO,5278906,84
9,CT,3593222,73
11,DC,647484,64
10,DE,926454,72
12,FL,19645772,79
13,GA,10006693,68
15,HI,1406299,87
19,IA,3093526,75
16,ID,1616547,77
17,IL,12873761,73
18,IN,6568645,76
20,KS,2892987,71
21,KY,4397353,76
22,LA,4625253,75
25,MA,6705586,69
24,MD,5930538,75
23,ME,1329100,71
26,MI,9900571,62
27,MN,5419171,72
29,MO,6045448,77
28,MS,2988081,73
30,MT,1014699,77
37,NC,9845333,70
38,ND,721640,73
31,NE,1869365,78
33,NH,1324201,71
34,NJ,8904413,72
35,NM,2084117,86
32,NV,2798636,91
36,NY,19673174,77
39,OH,11575977,77
40,OK,3849733,77
41,OR,3939233,75
42,PA,12779559,77
44,RI,1053661,78
45,SC,4777576,76
46,SD,843190,70
47,TN,6499615,70
48,TX,26538614,80
49,UT,2903379,79
51,VA,8256630,75
50,VT,626604,77
53,WA,6985464,71
55,WI,5742117,70
54,WV,1851420,79
56,WY,579679,76