Use multiple TopoJSON files to put layers on your map.
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
font-family: "Helvetica Neue", sans-serif;
}
.subunit.ac {
fill: #ddd;
stroke: #fff;
stroke-width: 1px;
}
.subunit.state {
fill: none;
stroke: #000;
stroke-width: .5px;
}
.subunit-boundary {
fill: none;
stroke: #3a403d;
}
.place-label {
font-size: .7em;
text-shadow: 1px 1px 1px #fcfcfc, 1px 1px 1px #eee, 0 -1px 0 #fff, -1px 0 0 #fff;
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script>
<script>
var width = window.innerWidth, height = window.innerHeight;
var projection = d3.geoMercator();
var path = d3.geoPath()
.projection(projection)
.pointRadius(2);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g");
d3.queue()
.defer(d3.json, "ac.json")
.defer(d3.json, "states.json")
.await(ready)
function ready(error, map, state){
centerZoom(map);
drawSubUnits(map, "ac");
var boundary = centerZoom(state);
drawOuterBoundary(state, boundary);
drawSubUnits(state, "state");
drawPlaces(map);
}
// This function "centers" and "zooms" a map by setting its projection's scale and translate according to its outer boundary
// It also returns the boundary itself in case you want to draw it to the map
function centerZoom(data){
var o = topojson.mesh(data, data.objects.polygons, function(a, b) { return a === b; });
projection
.scale(1)
.translate([0, 0]);
var b = path.bounds(o),
s = 1 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
projection
.scale(s)
.translate(t);
return o;
}
function drawOuterBoundary(data, boundary){
g.append("path")
.datum(boundary)
.attr("d", path)
.attr("class", "subunit-boundary");
}
function drawPlaces(data){
g.append("path")
.datum(topojson.feature(data, data.objects.places))
.attr("d", path)
.attr("class", "place");
g.selectAll(".place-label")
.data(topojson.feature(data, data.objects.places).features)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.attr("dy", ".35em")
.attr("x", function(d) { return projection(d.geometry.coordinates)[0] <= width / 2 ? -6 : 6; })
.style("text-anchor", function(d){ return projection(d.geometry.coordinates)[0] <= width / 2 ? "end" : "start"; })
.text(function(d) { return d.properties.name; });
}
function drawSubUnits(data, cl){
g.selectAll(".subunit." + cl)
.data(topojson.feature(data, data.objects.polygons).features)
.enter().append("path")
.attr("class", "subunit " + cl)
.attr("d", path);
}
</script>
</body>
</html>