Creating custom interactive maps on the web

2017-05-09

In this post, I will assume that you are familiar with shapefiles. First, you'll need to install TileMill (the now deprecated software in favour of Mapbox Studio). Even if it has been deprecated, it is a unique and powerful software that allows us to build maps from scratch. The goal of TileMill is to take a shapefile, style it with CartoCSS and export it as a .mbtiles file. mbtiles is a spec created by Mapbox to store raster images of a map.

Below is a screenshot from indiaunderconstruction.com that my friend Nikhil and I built recently.

If you're looking for advise, or need consultation with building map based data analysis and visualisation, you can contact me.

Fundamentals of web maps

A web map is usually a mercator projection (A projection is a transformation of our 3D world to a 2D map). There are different types of projection, and discussing all of those would be a digression. A web map should provide users a seamless experience of zooming, and panning across regions at various zoom levels. Thus, we can easily say that map interactions can be bound to 3 variables: z, x and y. At street level zoom, a single 2D image would be too big for the computer, therefore we serve the map as tiles, or smaller images, think of it as {z}/{x}/{y}.png, where we'll have that many images for different values of z, x, and y. Whenever the user pans left or right, we request for the appropriate image from the server in an AJAX call. This is handled by the wonderful library leaflet.js

Creating a map in TileMill

Download and install TileMill for your OS, and create a new project. Next, download shapefile data from your source. In the bottom left, you can add a layer in TileMill.

Styling with CartoCSS

CartoCSS is similar to CSS, with a few extra features. Below is the set of specifiers I've used to style my example map. The specifiers are for the dataset dgurbarg01m2014, some column name in the shapefile.

#dgurbarg01m2014[DGURBA_CLA=1] {
  polygon-opacity:1;
  polygon-fill:#3ff;
}

#dgurbarg01m2014[DGURBA_CLA=2] {
  polygon-opacity:1;
  polygon-fill:#168;
}

#dgurbarg01m2014[DGURBA_CLA=3] {
  polygon-opacity:1;
  polygon-fill:#000;
}

Notice that you can provide individual polygon fills based on column values in your shapefile data. The complete reference for CartoCSS can be found at https://tilemill-project.github.io/tilemill/docs/manual/carto/.

Hosting your own map server

Once it is styled, you can export it as a .mbtiles file, and then use mbutil to convert it to pngs with the z/x/y directory structure.

Finally, if your custom pngs are at /path/to/tiles, start $ python -m http.server from that folder. Once your tile server is up, below is a sample leaflet code to serve it on the browser.

L.tileLayer(`http://localhost:8000/{z}/{x}/{y}.png`, {
  subdomains: 'abcd',
  minZoom: 4,
  maxZoom: 12
}).addTo(map);

Refer to http://leafletjs.com/examples/quick-start/ if you haven't used leaflet already.

Note that this example tile server is for illustration purpose only. Do not use such a setup in production.

Conclusion

Creating maps are awesome fun!

There are plenty of shapefiles and GIS resources available online. Leaflet is also a wonderful library for map-based interactivity in the front end, in which you can show summarized data on hover, on click, etc. I hope you find this tutorial useful to start exploring on your own.