Building CampaignHawk: Spacial Analysis Overview (Part 16)

You may recall that we already have the ability to render our data through the featureLayer().addTo() functions that Mapbox gives us. That’s all well and good, but our data is not very convenient for Mapbox to render as is evidenced by the fact that it practically crashes the browser when it is asked to render the data layer. So the first thing we need to do is change our data.

Fortunately for us, somebody (Mapbox?) made Turf.js, which more or less does everything for us. Turf.js takes in GeoJSON data then spits out GeoJSON data after turning it into something useful. Thanks to our Meteor package, adding Turf.js is as simple as passing an object into Mapbox.load function. We’re going to want to add a few others as well.

plugins: ["turf", "markercluster", "omnivore"]

Between Turf.js and Mapbox, we should have all the tools we need to make some fancy maps. There are many useful functions that we will want to use. I’ll go over a few of them before I implement them so it’s more clear what it is they do.

The most pressing functionality we need to implement is clustering; without it, we render too many points at once (over 4000), which makes the app unusable. That’s where markercluster comes in.

Clustered data using markercluster. These can be styled however you like.

Another handy tool is the markercluster filter, which allows us to filter out certain information. This would be handy for data layers in which we want to filter out certain groups, for example a slider that filters out people who are not likely voters.

Turf-center lets us take the midpoint of a series of points. This will be helpful when we want to display the precinct name when zoomed out.

Turf-buffer displaying a circle around a point.

Turf-buffer takes a GeoJSON feature of any type and returns a buffer zone around it.

Since we have a lot of points, we will probably want to filter them in some meaningful way and show how they overlap with turf-buffer at some point.

Concave-hull and convex-hull take the outline of a set of points and makes a polygon (shown below). This will be handy to outline a voting district, or in our case, precinct_name.

A concave-hull showing the outline of certain points.

Turf-average calculates the average value of a field for a set of points within a polygon.

We can start thinking of examples of how we might use these in conjunction. For example, if we wanted to display congressional districts based on the average party score, we might filter for only one precinct_name, create a concave-hull around the precinct, take the turf-average of the party score of the precinct, then color the precinct on a spectrum from red to blue.

Another handy tool would be turf-envelope, which creates a rectangle that encompasses all points. This could be used to set the map starting location using the setView function so we don’t have to awkwardly zoom in every time.

Mapbox also allows us to toggle baselayers. So if we want to show a night-time view or a satellite view instead of the street view, we can do this quite easily.

Moving markers around is surprisingly easy.

It’s also possible to move markers around. If you’ve used Uber and spent an inordinate amount of time watching the cars move around, this is basically the same thing. This will help us accomplish our bonus specification of keeping track of our volunteers in real time.

We will also eventually want to implement Omnivore, which gives us the ability to add custom tooltips. This will allow us to click on a house to get more information about its inhabitants — very useful for the volunteers on the ground.

Lastly, but certainly not least important is toggling layers. Once again, Mapbox gives this to us for free with simple addLayer and removeLayer functions.

That should do it for the overview. Turf.js can do a bunch of other handy math for us which we will likely implement, but the examples above are the most important.

Next Steps

Now that we have a pretty good idea of what we want to do with our map, it’s time to implement some of these. We should probably start with markercluster so our map runs properly.