My Metro Bus Stops map shows all of Metro’s 11,485 bus stops. The file is 5.2 MB, so be patient while it loads.

The goal of the project was to demonstrate using WMATA‘s data and the Google Maps API.

The map lets you pan and zoom. You can hover over a pin to see the name of the stop and the zone, or click on the pin to zoom to that location. There is also an input field where you can enter any valid location, as understood by the Google Maps API. You can enter addresses, zip codes (20007, 20009), or place names (Arlington, DC, Dupont Circle, etc).

The bus data came from WMATA’s Developer Resources. They offer a “GTFS Download” which gives you a 15MB zip file containing 7 text files.

Then I wrote a PHP program to convert the data into HTML. It’s not worth it to do this on the fly, since the data so rarely changes. The static HTML loads faster and uses fewer server resources.

The map is drawn using the new canvas element in HTML5.

I used the Google Maps JavaScript API to configure the map and the pins.

Each pin required 6 lines of code:

point[234] = new google.maps.LatLng(38.957210, -76.869982);
marker[234] = new google.maps.Marker({map: map, position: point[234]});
marker[234].title = 'ANNAPOLIS RD & 85TH AV (zone 8)';
marker[234].icon = 'http://chart.apis.google.com/chart?chst=d_map_pin_letter_withshadow&chld=A|cc0000|cc0000';
google.maps.event.addListener(marker[234], 'click', function() {
   map.setZoom(20); 
   map.panTo(point[234]); });
bounds.extend(point[234]);

A point needs to be declared as a separate object before creating the marker because the API doesn’t allow for point literals, unfortunately. The marker’s title is automatically shown when the cursor hovers over it. For this program I am feeding it the bus stop location as the title.

Then I further customize the marker by choosing a pin design from Google Chart Tools. The next step adds an event, so that when you click on a pin the map will zoom and pan to that spot. The pins are shown in 32 colors, representing what WMATA’s data set refers to as a “zone ID,” though how to interpret this is still unknown.

Lastly, bounds.extend() is called to see if the map area needs to be expanded to include the new marker. Google does a great job of making this easy.

The Google map lets you choose between satellite and “map” views. I put map in quotes because the other view is of course also a map. I wish we had a better word to specify a “cartoon” version of the map, but, oh well. As an enhancement, I added another option, to use a map from openstreetmap.org.

And I should mention there is another Google toy in the code, for Google Analytics, a topic for another post.

Mapping Metro’s 11,485 Bus Stops

Leave a Reply