Using JavaScript to Create Geospatial and Advanced Maps
Until recently, developing geospatial apps beyond a 2D map required a comprehensive GIS service such as ArcGIS, Nokia Here, or Google Maps. While these APIs are powerful, they are also expensive, onerous to learn, and lock the map developer to a single solution. Fortunately, there are now a wealth of useful, open source JavaScript tools for handling advanced cartography and geospatial analysis.
In this article, I’ll examine how to implement GIS techniques with JavaScript and HTML, focusing on lightweight tools for specific tasks. Many of the tools I’ll cover are based on services such as Mapbox, CloudMade, and MapZen, but these are all modular libraries that can be added as packages to Node.js or used for analysis in a web browser.
Note: The CodePen examples embedded in this post are best viewed on CodePen directly.
Geometry & 3D
Distance and Measurement
It is especially useful to have small, focused libraries that perform distance measurement, and conversion operations, such as finding the area of a geo-fence or converting miles to kilometers. The following libraries work with GeoJSON formatted objects representing geographic space.
- Geolib provides distance (and estimated time) calculations between two latitude-latitude coordinates. A handy feature of Geolib is order by distance, which sorts a list or array by distance. The library also supports elevation.
- Turf.js, which is described in the next section, also provides a distance function to calculate the great-circle distance between two points. Additionally, Turf.js calculates area, distance along a path, and the midpoint between points.
- Sylvester is a library for geometry, vector, and matrix math in JavaScript. This library is helpful when basic measurement of lines and planes is not enough.
3D
While the above libraries work well for 2D projections of geography, three-dimensional GIS is an exciting and expansive field—which is natural because we live 3D space. Fortunately, WebGL and the HTML5 canvas have also opened up new 3D techniques for web developers.
- Three.js is a JavaScript library for geometric and mesh objects. The Three GeoJSON extension to Three.js provides a simple way to render GeoJSON objects on 3D planes and spheres.
- The OSM Buildings project allows the map designer to represent buildings as 3D objects on a 2D map. The project uses OpenLayers and Leaflet. This can be used to great effect, for example Tom Holdernessused OSM Buildings to map London.
Here’s an example of how to display GeoJSON Features on a 3D object:
You can also check out Byron Houwen’s article on WebGL and JavaScript, which shows how to create a terrain map of earth with Three.js
Geo Features & Points
Much of the work in GIS involves dealing with points, shapes, symbols, and other features. The most basic task is to add a shape or point features to a map. The well-established Leaflet library and newcomer Turf.js make this much easier and allow users to work with feature collections.
- Leaflet is simply the best option for working with the display of points, symbols, and all types of features on web and mobile devices. The library supports rectangles, circles, polygons, points, custom markers, and a wide variety of layers. It performs quickly and handles a variety of formats. The library also has a rich ecosystem of third-party plug-ins.
- Turf.js is a library from Mapbox for geospatial analysis. One of the great things about Turf.js is that you can create a collection of features and then spatially analyze, modify (geoprocess), and simplify them, before using Leaflet to present the data. Like Geolib, Turf.js will calculate the path length, feature center, points inside a feature.
- Simple Map D3 creates choropleths and other symbology by simply defining a GeoJSON object and data attribute.
The following is an example of using Turf.js to calculate the population density of all counties in the state of California and then displaying the results as a Leaflet choropleth map.
A key concept in Turf.js is a collection of geographic features, such as polygons. These feature are typically GeoJSON features that you want to analyze, manipulate, or display on a map. You start with a GeoJSON object with an array of county features. Then, create a collection from this object:
1
|
collection = turf.featurecollection(counties.features); |
With this collection you can perform many useful operations. You can transform one or more collections with joins, intersections, interpolation, and exclusion. You can calculate descriptive statistics, classifications, and sample distributions.
In the case of population density, you can calculate the natural breaks (Jenks optimization) or quantile classifications for population density:
1
|
breaks = turf.jenks(collection, "pop_density" , 8); |
The population density (population divided by area) value was calculated and stored as a property of each county, but the operation works for any feature property.
Working with Points
Points are a special type of geographic feature representing a latitude-longitude coordinate (and associated data). These features are frequently used in web applications, e.g. to display a set of nearby businesses on a map.
Turf.js provides a number of different operations for points, including finding the centroid point in a feature and creating a rectangle or polygon that encompasses all points. You can also calculate statistics from points, such as the average based on a data value for each point.
There are also extensions for Leaflet.js that help when dealing with a large number of points:
- Marker Cluster for Leaflet is great for visualizing the results from Turf, or a collection of points that is large. The library itself handles hundreds of points, but there are plugins like Marker Cluster and Mask Canvas for handling hundreds of thousands of points.
- Heat for Leaflet creates a dynamic heat map from point data. It even works for datasets with thousands of points.
Geocoding & Routing
Routing, geocoding, and reverse geocoding locations requires an online service, such as Google or Nokia Here, but recent libraries have made the implementation easier. There are also suitable open source alternatives.
The HTML5 Geolocation API provides a simple method of getting a device’s GPS location (with user permission):
1
2
3
|
navigator.geolocation.getCurrentPosition( function (result){ // do something with result.coords ); |
Location-aware web applications can use Turf.js spatial analysis methods for advanced techniques such as geofencing a location inside or outside of a map feature. For instance, you can take the result from the above example and use the turf.inside method to see if that coordinate is within the boundaries of a given neighborhood.
- GeoSeach is a Leaflet plugin for geocoding that allows the developer to choose between the ArcGIS, Google, and OpenStreetMaps geocoder. Once the control is added to the base map, it will automatically use the selected geocoding service to show the best search result on the map. The library is designed to be extensible to other third-party services.
- Geo for Node.js is a geocoding library that uses Google’s Geocode API for geocoding and reverse geocoding. It additionally supports the Geohash system for URL encoding of latitude-longitude coordinates.
As with geocoding, there are myriad routing and direction services, but they will cost you. A reliable, open source alternative is the Open Source Routing Machine (OSRM) service by MapZen. It provides a free service for routing car, bicycle, and pedestrian directions. Transit Mix cleverly uses the OSRM Routing tool for creating routes in their transportation planning tool.
Spatial and Network Analysis
I’ve mentioned a few spatial analysis methods you can implement with Turf.js and other libraries, but I’ve only covered a small part of a vast world. I’ve created an example application that illustrates several of the techniques I’ve introduced.
Conclusion
In this article I hope to have provided a comprehensive overview of the tools which are available to perform geospatial analysis and geoprocessing with JavaScript. Are you using these libraries in your projects already? Did I miss any out? Let me know in the comments.
If you want to go even further with geospatial analysis and geoprocessing with JavaScript, here are a few more resources and utilities:
- NetworkX and D3.js — Mike Dewars’ book on D3.js includes a number of examples of using D3 with maps and spatial analysis. One of the more interesting examples is creating a directed graph of the New York Metro, which is done by analyzing the Google Transit specification for MTA with NetworkX.
- Simply.js — Turf uses Vladimir Agafonkin’s Simply.js to perform shape simplification. That library can also be installed as an independent Node.js package for online or offline processing of files.
- d3 Geo Exploder — Ben Southgate’s d3.geo.exploder allows you to transition geographic features (geoJSON) to another shape, like a grid or a scatter plot.
- Shp — Use this library to convert a shapefile (and data files) to GeoJSON
- ToGeoJSON — Use this library to convert KML & GPX to GeoJSON
- Shp2stl – Use this library to convert geodata into 3D models that can be rendered or 3D printed.
- MetaCRS and Proj4js— use these libraries to convert between coordinate systems.