This tweak to my original example uses a Mercator projection rather than Albers USA, which straightens out many of the state borders and puts Alaska and Hawaii in their right places.
<!DOCTYPE html>
<html>
<head>
<title>d3 geo thumbnails</title>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<style>
svg.thumb {
width: 90px;
height: 94px;
display: block;
float: left;
margin: 5px 0 0 5px;
}
path {
vector-effect: non-scaling-stroke;
stroke-width: 1;
}
.thumb .bg,
.thumb use {
fill: #ddd;
stroke: #ccc;
}
.thumb .fg {
fill: #8cba3d;
stroke: none;
}
</style>
</head>
<body>
<div id="thumbnails"></div>
<svg id="shared">
</svg>
<script>
var root = d3.select("#thumbnails"),
proj = d3.geo.mercator()
.center([-98, 38]),
path = d3.geo.path()
.projection(proj),
// how much space to give the features from
// the edge of their container
margin = 10;
d3.json("us-states.json", function(error, topology) {
var collection = topojson.feature(topology, topology.objects["states"]);
// draw the whole collection once to a path in the shared <defs>
d3.select("#shared")
.append("defs")
.append("path")
.datum(collection)
.attr("id", "states-bg")
.attr("d", path);
// sort the states by name
collection.features.sort(function(a, b) {
return d3.ascending(a.properties.name, b.properties.name);
});
// filter out the territories & DC
var states = collection.features.filter(function(d) {
return +d.id <= 70 && d.id != 11;
});
var svg = root.selectAll(".thumb")
.data(states)
.enter()
.append("svg")
.attr("id", function(d) {
return d.properties.name;
})
.attr("class", "thumb")
.attr("viewBox", function(d) {
// get the projected bounds
var bounds = path.bounds(d),
width = bounds[1][0] - bounds[0][0],
height = bounds[1][1] - bounds[0][1],
// get the proportion of the bounds' longest side
// to the container's shortest side
scale = Math.max(width, height) / Math.min(this.offsetWidth, this.offsetHeight),
// and multiply the desired margin by this
m = margin * scale;
return [
bounds[0][0] - m,
bounds[0][1] - m,
width + m * 2,
height + m * 2
].join(" ");
});
// place the shared states path here
svg.append("use")
.attr("xlink:href", "#states-bg");
// and draw the individual states on top
svg.append("path")
.attr("class", "fg")
.attr("d", path);
});
</script>
</body>
</html>