|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>d3 geo thumbnails</title> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://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.albersUsa(), |
|
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> |