Skip to content

Instantly share code, notes, and snippets.

@mpmckenna8
Created April 1, 2017 23:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mpmckenna8/af23032b41f0ea1212563b523e859228 to your computer and use it in GitHub Desktop.
Save mpmckenna8/af23032b41f0ea1212563b523e859228 to your computer and use it in GitHub Desktop.
Topojson on a leaflet map

Using topojson with Leaflet.js and coloring your polygons based on color.

So I saw a nice example of usng geojson right on the Leaflet.js tutorials examples but I wanted to make a little thing to show how to use topojson, even though for this dataset there aren't too many shared topologies (borders) so it doesn't make a ton of sense to convert stuff from geojson to topojson to serve it to be converted to geojson again on the client.

But there might be datasets where it actually helps. Especially when you have a lot of shared borders and you want to not color any neighbors the same color. Topojson clientside has a really nice function where it finds each polygon's neighbors and then when you're assigning them colors you can make sure the ones next to each other don't have the same color.

The way topojson is used here is not particularly effective because there are a number of islands of polygons in close proximity to each other and the first polygon in each group will get the same color. So a few small groups of polygons close together will only make use of the first few colors in the color selection array. Maybe in my next post I'll make it so that it will use actually make use of all the colors using a modulo thing and a counter variable in the parent scope of the style funciton.

But for now I just want to join some data to these polygons so I can make a choropleth map. Look for a block or project with that in the near future.

This example was pretty much just a hacked up version of: http://leafletjs.com/examples/choropleth/

Feel free to let me know if there's anythong silly in the code or change it yourself and show me.

<html>
<head>
<link rel="stylesheet" href="./style.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
</head>
<body>
<!--
Need to add some styling to my map and figure out if I'm going to change all that jam up there in the script. just wanted to kind of start the quickstart tutorial.
-->
<div class="map" id="mapcon"></div>
<script type="text/javascript">
var god;
var neighbors;
var geoschools = {};
var geojson;
var co = d3.scaleOrdinal(d3.schemeCategory20b);
window.onload = function () {
var neighbors
function style(feat, i){
var i = feat.indie;
var coco = co(feat.color = d3.max(neighbors[i], function(n) {
return geoschools.features[n].color; }) + 1 | 0);
return {fillColor: coco,
fillOpacity: .8,
weight: .8}
}
var req = new XMLHttpRequest();
var url = './schoolsca.topojson'
req.open('GET', url, true);
req.onreadystatechange = handler;
req.send();
var topoob = {};
geoschools = {};
function handler(){
if(req.readyState === XMLHttpRequest.DONE){
var layer = "terrain";
var map = new L.Map('mapcon',
{
center: new L.LatLng(37.8, -122.4),
zoom: 10
});
var OpenStreetMap_BlackAndWhite = L.tileLayer('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
});
map.addLayer( OpenStreetMap_BlackAndWhite)//new L.StamenTileLayer(layer));
// try and catch my json parsing of the responseText
try {
topoob = JSON.parse(req.responseText)
neighbors = topojson.neighbors(topoob.objects.caschools.geometries);
geoschools = topojson.feature(topoob, topoob.objects.caschools)
geoschools.features = geoschools.features.map(function(fm,i){
var ret = fm;
ret.indie = i;
return ret
});
geojson = L.geoJson(geoschools, {style:style, onEachFeature: onEachFeature})
.addTo(map);
console.log('neigh', neighbors)
}
catch(e){
geojson = {};
console.log(e)
}
console.log(geoschools)
function highlightFeature(e){
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#665',
dashArray: '',
fillOpacity: .7})
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
info.update(layer.feature.properties);
}
function resetHighlight(e){
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer){
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight, click: zoomToFeature})
}
var info = L.control();
info.onAdd = function(map) {
this._div = L.DomUtil.create('div', 'info');
this.update();
return this._div;
}
info.update = function(props){
this._div.innerHTML = "<h4>California School Districts</h4>" +
(props ? '</br>' + props.NAME + '</br>' : "Hover " +
"over a school district")
}
info.addTo(map);
}
}
}
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment