Having done few projects with Processing.js, I was looking for next opportunity to use Paper.js for a decent sized project and up came the olympics visualization challenge courtesy of folks from Visualizing.org The goal of this visualization is to map how in the last 6 summer olympics countries with total medals compare in terms of GDP per capita. Let’s briefly go over the process I used for building this visualization.
I decided to just copy paste total medals tally from London2012.com website for each of last 6 summer olympics into a csv and added extra column with corresponding GDP per capita for the country(from Worldbank.org)
I am using a sinatra app to read in the csv and return it in json format, so the index endpoint just renders the html whereas /countries endpoint returns the json data for that specific event year.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Building the visualization
- Here’s the basic pseudocode for the paperscript code:
- Load the olympics data in json format for each year, store them as OlympicEvent object in array
- Each of those countries are stored as Node object with necessary attributes like medal counts, gdp per capita, country name and so forth.
- In initial state, draw overview of each olympic event(total medals, participating countries, medal winning countries..)
- Draw the interactive state, where each node(country) for each event is represented by a circle, size of which represents total medals, and y-position in the 2D space represents the GDP per capita in that year. This is done in onMouseClick() event handler, so first time you click on the canvas, initial state gets replaced by interactive state.
- To achieve some level of interaction, implement onMouseMove() handler where we check if cursor is over any node(country) and illuminate that country(while seting opacity to half for rest of the nodes)
- Finally clicking inside a node shows a history of that particular country, displaying the difference in GDP per capita and medals count in succesive events. This is obviously in the onMouseClick() event where initialState is false already.
Since x-axis maps to year of the olympic event, I set aside a width of about 170px(just through trial and error) for each year to allow nodes to space out and not be colliding with each other. Here’s the rather naive/simple collision detection I used, where node is moved n units to the right if colliding with another node:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
I did use underscore.js rather heavily, mainly for routines like map, each and find. The end code is still quite verbose, mainly due to repetitive tasks like drawing labels in different places and so forth, which can be DRYed up a bit. Overall I liked working with Paperjs and getting used to its API, its somewhat similar to Processing API which is what I am most familiar with. I have put the whole source code, including the sinatra app up in github: https://github.com/nandayadav/olympics_visualization And here’s the endproduct: Olympics GDP vs Medals Visualization