Following my recent trip to Iceland (which I highly recommend), I wanted to visualize the trip using a map, complete with the route and stop locations along the way.
Source code
Full source code for this project can be found on Github
In order to use the Mapbox API you will need an access key, and for that you need to have a user account. For smaller projects, I recommend using the starter plan which is free to use (https://www.mapbox.com/pricing/)
Once your account is set up, you can find your API key by following this URL https://www.mapbox.com/studio/. It will be under the “Access Token” section.
Prepare python environment
Create a virtual environment with the following packages:
Create a flask project
Create the folders for the project:
We’ll put our main files in the flask_mapbox folder.
The static folder will be used for CSS, Javascript and images, while the
templates folder will be used for HTML files
Create a server.py file for the python code:
Create a bash script to that will set the environment variables needed to start the server:
That’s it, the server is ready to run!
Open the command line console and run the start.sh file:
Browse to http://127.0.0.1:5000/. For now, you’ll only get a 404 page not found error as we are not doing anything yet.
Display a simple map
In this part you will learn how to display a map using the Mapbox API.
As we don’t want to put the API key as part of the code, start by putting it in a configuration file.
Create a new file with the name settings.py in the root folder of the project and add the following code:
Add an additional environment variable in start.sh that will point to settings.py.
start.sh should look like:
In server.py read the settings.py configuration file from the environment variable and get the access key from the configuration file:
Next, create a function in the server.py file that will route to the new template templates/mapbox_js.html.
The function should also send the Mapbox access key to the template.
Finally, we want to create the HTML file that will show the map.
In the templates folder, create a new HTML file with the name mapbox_js.html for showing the map.
In the HTML header we will load the css and javascript from Mapbox.
In the JavaScript section of the HTML we will set the Mapbox access key that we got from the server, and create a new map object in the <div id="map"> element.
We will set the map to show Iceland ([65.0,-18.73]) with zoom level of 7.
The mapbox_js.html file should look like this:
You can start the server again by running the start.sh file:
The function create_route_url will create the API URL with all of our geo-coordinates and the Mapbox access token.
The get_route_data function will use requests to run the API request and return the results as a GeoJSON object:
We’ll modify the previous mapbox_js function and add the routing data to the render_template function:
In the mapbox_js.html file add a Mapbox feature layer with the routing data.
Add the following code to the JavaScript section in mapbox_js.html:
Start the server again by running the start.sh file:
Browsing to http://127.0.0.1:5000/mapbox_js will show a page with a Mapbox map and the routing (the black line) starting in Keflavík International Airport (KEF), going around Iceland and ending in Reykjavík:
Add location markers on the map
Next, we’ll add location markers for cities and locations along the route.
We’ll edit the ROUTE dictionary with the location names (name) and a boolean to signal if this is a stop location (is_stop_location) for locations that we stopped in along the way.
In server.py edit the data in ROUTE:
In the server.py file, we’ll declare a function to create GeoJSON objects for markers.
These marker objects will have the latitude, longitude and different properties such as title, icon, marker color and the number of marker along the way.
The new function will look like this:
In the template, we’ll set a new feature layer with the stop locations data:
Some time ago, Mapbox released a new framework, Mapbox GL.
While Mapbox GL is still considered a new framework, it might be the future replacement for Mapbox.js (Leaflet plugin).
In this part, we will convert our code to user Mapbox GL and show some of the differences between the two frameworks.
We’ll start by creating a new function in server.py that will route to a new template that uses Mapbox GL:
Create a new template templates/mapbox_gl.html and add the following code:
This time we use the mapbox-gl JavaScript and CSS.
In the JavaScript section we’ll create a new mapboxgl.Map object.
the mapboxgl object is set with the id of the relevant div, the style of the map, latitude and longitude of the center of Iceland and the zoom level for the map.
Add the route data using the same get_route_data function that we used previously:
In the mapbox_gl.html template, add the following to the JavaScript section after the initialization of the map object.
This time, in the JavaScript part of the HTML we first create a source with the routing data for the map and then we add a layer using the source object that we just created.
Adding the markers is a bit different with Mapbox GL, as it is more of a manual process.
From the server side, we send the markers in the same way as we did before:
On the HTML side, in templates/mapbox_gl.html add the following css:
The configuration uses a file called marker.png which can be found in my Github repository.
Put marker.png in the templates folder.
In the JavaScript part of templates/mapbox_gl.html, load the stop locations data structure and add a marker for each stop location.
Going to http://127.0.0.1:5000/mapbox_gl will show the map of Iceland with the route along the ring road, and with markers in the stop locations:
Adding map animations
We can also add an animation on top of our map.
For this example, we will add an animation of a car going through the route between the stop locations.
We start by adding a new source and layer for the car icon that we will animate across the route.
On the client side, add the following code to the JavaScript section in mapbox_gl.html inside the map load function:
Add the animation function for moving the car along the route:
On the server side, we need to add a couple of additional details to the stop locations so we can move the car between them.
Add the following code to the server side:
On the client side, we’ll add buttons that will control the location of the car on the route