Author: Ben Kennedy
Geovis Project Assignment @RyersonGeo, SA8905, Fall 2021
Data referenced contains information licensed under the Open Government Licence – City of Ottawa.
Early on, when thinking about the project, I decided I wanted to choose a technology I had little to no exposure to and really dive deep into how it worked and what it was capable of. I looked through several different technologies and eventually decided on Mapbox as a result of William Davis’ site and the vast array of cool interactive projects using it as their platform. Mapbox is a platform specifically for web or application maps that gives the user an incredible degree of control over the appearance of all aspects of a map. It does this by providing a studio interface (GUI) where a user can customise a basemap by importing shape files, geojson files, image files, etc. Once you’ve edited this basemap to your satisfaction you can export the map as a url and link it directly into an html document.
My initial idea was to use time series data with a slider to visualize bike accidents in my home city (Ottawa) over a number of years. However, because of how Mapbox methods and functions work (more on this later) I chose to use a slider to run through the numbers of accidents by intersection from a particular year. With this in mind I began the construction of my website (and more tutorials on Mapbox methods than I care to remember)…
The next step was to upload a shapefile of the accident points from 2013, obtained from the City of Ottawa open data portal, to Mapbox. Mapbox acts as a host for shape files, geojson, etc. that you upload to it, and converts all these formats into tilesets that you can call in your map by referencing a url. You can also add these tilesets directly into your basemap, however this makes them harder to work with when you eventually switch over to code. For this map, I chose to add a shapefile of the City of Ottawa neighbourhoods directly to my basemap since I had no interest in making this layer interactive. I also uploaded a shapefile containing the cycling network for the City to my basemap just out of personal interest. The file containing the accident points and information was left as a tileset and not added to the basemap so we could easily call it when developing our interactive elements.
Now that I had my data uploaded and my basemap complete it was time to move into a code editor and put together my webmap.
A Daunting Amount of Code
Now, when you first look at the code for this webmap it can appear quite daunting, I certainly felt that way when I first tried to figure it out. You’ll need a few things to actually start editing your html page: 1. You need to go download the node.js repository, this is what Mapbox methods and fuctions run on. 2. You’ll need a good editor/compiler and a live server of some sort so you can see your changes in real time. I used Atom as my editor and then a free live server called “atom-live-server” which is available through atoms tools library. I also played around with creating a python local server – hosted from my PC, but this is quite complicated and it’s much easier to use the available tools.
Once you’ve got all this together it’s time to start putting together your webpage. You can either code it entirely from scratch or base it on a pre-existing project. Since I had little to no experience with html and CSS I chose to take one of Mapbox’s example projects and edit it using my own maps and functions. What this means is that the basics of the page itself were already set up, however none of the information was present. So, for example, the slider element was in the webpage, but none of the information you could scroll through was present, nor was there a method linking the slider to a filter for that information.
So, on to Mapbox and it’s various methods and functions. First off was to add the basemap as the “map element” on our webpage. This was done by plugging the url into the “style” field of the map element. This essentially imports the full style that you’ve created in the GUI. When doing this it’s also important to set your starting zoom and centre point. If you don’t do this, Mapbox will default to a full world zoomout and place you at the projection centre. Here I chose a starting zoom of 9.1, which gives a good overview of the City of Ottawa and a centre sitting smack in the middle of the City.
Next, we call the tileset containing the collision points. I have to admit it took me a full week of work to get this part right. Mapbox has a ton of different ways of styling these layers that you can play with directly in the code. However, ashamed as I am to admit it, my major issue here was not adding the “mapbox://” before my tileset id. This is very important, without this your map will just appear blank, as you are adding a layer that for all intents and purposes does not exist to Mapbox. Once I had eventually figured this out I went ahead and added the layer with a few style options worked out. The three major things I chose to style with the layer were: 1. I set the circle radius to grow with the number of cyclist collisions per point. This was done using a “get” function on the “2013_CYCLI” field that was part of the collisions shapefile. 2. Next, I interpolated the colour of the points, again on the number per intersection, just to give a little more distinction. 3. Finally, and this is a very important step, I set a filter on the “2013_CYCLI” field that would ensure only points with cyclist collisions would be added to the map.
Let’s Add Some Interactivity
Our next step was to link the slider element of our html page to a function that would allow it to filter data. I used a very simple setup for this that would run through the “2013_CYCLI” field and filter the intersections by position on the slider. To do this, I created a variable that stored the slider position as an integer. I then used a “filter” function to go through the layer and pull all accidents with that value or higher. So now the slider would let you go through all the accidents in 2013 and look at all collisions involving cyclists, locations with 2 or more cyclist collisions, and locations with 3 or more cyclist collisions. Essentially, you can see which intersections in Ottawa are the most dangerous for cyclists.
The final touch was to call another layer from openstreetmap and overlay it so you were able to see the road network. With this done, the webmap was complete and ready to be shared.
To share the map I chose to use Github pages. The process is relatively simple once you get going. The first thing to do is to ensure that your html file is called “index” – this is the root file for a github pages site as you are able to add several different pages to any site you create. As we were just sharing the single page, calling it index ensures that it’s always displayed when you load the site. Next you upload the html file to Github, or you link the folder on your machine to github through the github desktop app, I found this super useful as Atom (the code editor I was using) has github desktop integration. And voila, once you’ve enable the pages option in your github repository settings, you can share the link with whomever you’d like!
And here, in fact, is the link to the final product: https://benken97.github.io/SA8905Final/
I do think it would be remiss not to mention a few of the issues I had: 1. The major one was the lack of tutorials for Mapbox. While there is a lot of examples and their API and style reference is exhaustive, a lot of the issues I ran into could have been solved very easily if a solid online tutorial library focused on the basics (they do have one but it’s not that helpful for beginners) existed. The second major issue was my complete lack of knowledge when it came to html and CSS. I was able to learn a fair bit as I went but in the end there are a few portions that I wish I could polish up. Specifically, adding tickmarks and a legend to the slider would have been a very useful feature and I spent hours trying to figure that one out. Unluckily not every browser supports tickmarks and/or legends so I ended up just giving the range by the title. Finally, I do wish that the data I was dealing with had been limited to cycling incidents, as the inclusion of all collisions forced me to filter by cyclist collision rather than year.