Skip to content

Instantly share code, notes, and snippets.

@JoeGermuska
Last active February 14, 2017 02:50
Show Gist options
  • Save JoeGermuska/2606a5311d0be5889ba7 to your computer and use it in GitHub Desktop.
Save JoeGermuska/2606a5311d0be5889ba7 to your computer and use it in GitHub Desktop.
Put Census shapes on your map

If you want to add Census shapes to your leaflet map, why not use Census Reporter's data?

To get some idea of what's available, pick a summary level from the menu at the top of the page. Depending on the summary level, the map will zoom to a sort of arbitrarily "close" level. This is because our server will, like a loyal dog, try to fetch all the features at whatever you ask for, but it doesn't deal very well with requests for lots of features. You can experiment a little by zooming out after you pick a small summary level. Of course, while you're doing that, you're sorta grinding our servers, so don't go nuts.

Note: We're working on encapsulating this into something you can do even more simply. Just need to work out a few fine points of default behavior and how much we need to do to actually make it simple.

We would love to refine this service so that it works more flexibly for all summary levels and zoom levels, but we might need some engineering consulting to work that out. If you'd like to contribute that kind of support, please tweet at @CensusReporter or otherwise contact us.

Hopefully you can read the source of the page and figure out how to add the layers to your map using Leaflet. We

FAQ

Can I get just the counties for a single state? (and so forth)

There's no filtering right now. I agree, that would be cool. It would muck with our caching strategy, but we would be happy to talk further about how to solve that if you're of a mind to volunteer time and/or code.

Summary Levels

  • 020: region
  • 030: division
  • 040: state
  • 050: county
  • 060: county subdivision
  • 140: census tract
  • 150: block group
  • 160: place
  • 170: consolidated city
  • 230: Alaska native regional corporation
  • 250: native area
  • 251: tribal subdivision
  • 256: tribal tract
  • 310: metro area
  • 314: metropolitan division
  • 330: combined statistical area
  • 335: combined NECTA
  • 350: NECTA
  • 364: NECTA division
  • 400: urban area
  • 500: congressional district
  • 610: state house (upper)
  • 620: state house (lower)
  • 795: PUMA
  • 860: ZIP code
  • 950: school district (elementary)
  • 960: school district (secondary)
  • 970: school district (unified)
<!DOCTYPE html>
<html>
<head>
<title>Example of using Census Reporter GeoJSON tiles on your own maps.</title>
</head>
<body>
<select id="sumlev-picker">
<option> -- pick a summary level -- </option>
</select>
<div id="map" style="width: 100%; height: 100%;"></div>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="//cdn.jsdelivr.net/g/[email protected],[email protected],underscorejs"></script>
<script src="http://censusreporter.org/static/js/TileLayer.GeoJSON.js"></script>
<script type="text/javascript">
// make it big
var sumlevs = [
{ 'level': '020', 'name': 'region', zoom: 4 },
{ 'level': '030', 'name': 'division', zoom: 4 },
{ 'level': '040', 'name': 'state', zoom: 4 },
{ 'level': '050', 'name': 'county', zoom: 7 },
{ 'level': '060', 'name': 'county subdivision', zoom: 7 },
{ 'level': '140', 'name': 'census tract', zoom: 10 },
{ 'level': '150', 'name': 'block group', zoom: 15 },
{ 'level': '160', 'name': 'place', zoom: 9 },
{ 'level': '170', 'name': 'consolidated city' },
{ 'level': '230', 'name': 'Alaska native regional corporation' },
{ 'level': '250', 'name': 'native area', zoom: 4 },
{ 'level': '251', 'name': 'tribal subdivision', zoom: 4 },
{ 'level': '256', 'name': 'tribal tract', zoom: 4 },
{ 'level': '310', 'name': 'metro (CBSA) area', zoom: 7 },
{ 'level': '314', 'name': 'metropolitan division', zoom: 4 },
{ 'level': '330', 'name': 'combined statistical area', zoom: 4 },
{ 'level': '335', 'name': 'combined NECTA', zoom: 4 },
{ 'level': '350', 'name': 'NECTA', zoom: 4 },
{ 'level': '364', 'name': 'NECTA division', zoom: 4 },
{ 'level': '400', 'name': 'urban area', zoom: 7 },
{ 'level': '500', 'name': 'congressional district', zoom: 7 },
{ 'level': '610', 'name': 'state house (upper)', zoom: 7 },
{ 'level': '620', 'name': 'state house (lower)', zoom: 7 },
{ 'level': '795', 'name': 'PUMA', zoom: 8 },
{ 'level': '860', 'name': 'ZIP code', zoom: 12 },
{ 'level': '950', 'name': 'school district (elementary)', zoom: 10 },
{ 'level': '960', 'name': 'school district (secondary)', zoom: 10 },
{ 'level': '970', 'name': 'school district (unified)', zoom: 10 }
]
var div = document.getElementById("map");
div.style.height = (window.innerHeight - 100) + "px";
var baseLayer = function() {
return L.tileLayer('http://a.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: { 'name': 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>' },
maxZoom: 18
});
}
// pretty basic Leaflet here...
var map = L.map("map")
map.setView([39.833333, -98.583333], 5);
map.addLayer(baseLayer());
var defaultStyle = {
"clickable": true,
"color": "#00d",
"fillColor": "#ccc",
"weight": 1.0,
"opacity": 0.3,
"fillOpacity": 0.3,
};
// more about sumlevs at http://censusreporter.org/glossary/#term-summary-level
var defaultSumlev = '040';
var makeLayer = function(sumlev) {
var tilesGeoAPI = 'http://embed.censusreporter.org/1.0/geo/tiger2013/tiles/' + sumlev + '/{z}/{x}/{y}.geojson';
var geojsonTileLayer = new L.TileLayer.GeoJSON(tilesGeoAPI, {
clipTiles: true,
unique: function(feature) {
return feature.properties.geoid;
}
}, {
style: defaultStyle,
onEachFeature: function(feature, layer) {
// you can wire behavior to each "feature", or place outline.
var profileURL = 'http://censusreporter.org/profiles/' + feature.properties.geoid;
layer.bindPopup("<a href='" + profileURL + "'>" + feature.properties.name + "</a>");
layer.on('mouseover', function() {
layer.setStyle({
"fillOpacity": 0.5,
});
});
layer.on('mouseout', function() {
layer.setStyle(defaultStyle);
});
}
});
return geojsonTileLayer;
}
_.each(sumlevs,function(l) {
$('<option>').val(l.level).text(l.level + " - " + l.name).appendTo('#sumlev-picker');
});
$("#sumlev-picker").change(function(e) {
var sumlev = _.findWhere(sumlevs,{level: $(e.target).val()})
if (sumlev) {
if (sumlev.zoom) {
map.setZoom(sumlev.zoom);
}
if (typeof sumlev.layer == 'undefined') {
sumlev.layer = makeLayer(sumlev.level);
}
_.each(sumlevs,function(sl) {
if (sl.layer && map.hasLayer(sl.layer)) {
map.removeLayer(sl.layer);
}
})
map.addLayer(sumlev.layer);
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment