Drawing a Google Map with Data from an API

Published Jun 17, 2015Last updated Feb 14, 2017
Drawing a Google Map with Data from an API

Note: The maps shown in the tutorial are all screenshots, to make sure everyone reading this has the same experience.

Integrating dynamic maps like those from the Google Maps API is a bread-and-butter item on the web. Like many things in browser development, though, it can take a few times through to get your head around everything that needs to happen!

In this tutorial, we're going to integrate data from two sources to draw a map, and place markers on it:

  • Access the user's location via the browser's Navigator API (documentation)
  • Retrieve nearby points of interest via an API (in our case, the Starbucks Stores API) (API home)
  • Draw a Google Map of the user's neighborhood using the Google Maps JavaScript API (documentation)
  • Draw markers on the map at the retrieved Starbucks locations
  • Show name of each Starbucks location when the user hovers over its marker

Note that both the browser location call and the AJAX call to the Starbucks API are performed asynchronously, so if you aren't comfortable with callbacks yet, check out this intro to async programming.

Our code

Following the agile maxim of "make it work, then make it right," we'll start coding inline in an HTML page. We can extract the JavaScript we create into its own file later. Here's the empty map div and script element we'll start with:

<html>
  <head></head>
  <body>
    <div id="map-canvas" style="height: 600px; width: 600px;"></div>

    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAK82k3-3glRm_PJfQ6bzjQMiKgXeU8DoQ"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

    <script>
      // our functions go here...

      $(document).ready(function() {
        // ...and the code for initializing the page build goes here
      });
    </script>
  </body>
</html>

User's Location with navigator.geolocation

Modern browsers allow us to request the user's location, but we'll need to serve this page on a local web server -- it won't work to browse the file directly using the file:/// protocol. A comprehensive guide to this is out of scope, but this generally works on Unix-like systems, on the command line when in the directory where your file is:

$ python -m SimpleHTTPServer

Back to our JS code -- the geolocation result is provided asynchronously via a callback:

navigator.geolocation.getCurrentPosition(function(position) {
  console.log(position);
}, function(error) {
  console.log(error);
});

When the location call succeeds, the first callback is run. If there is an error, or the user blocks the request, the second callback is run. The success result looks like this:

{
  coords: {
    accuracy: 30,
    altitude: null,
    altitudeAccuracy: null,
    heading: null,
    latitude: 40.8036842,
    longitude: -74.1010033,
    speed: null
  },
  timestamp: 1434464159510
}

Use the Location to Retrieve Data from an API

As of this writing, Starbucks has a handy API for retrieving store locations -- so let's do it!

var positionToStarbucksLatlng = function(position) {
  return position.coords.latitude + ',' + position.coords.longitude;
};

navigator.geolocation.getCurrentPosition(function(position) {
  $.ajax({
    url: 'https://testhost.openapi.starbucks.com/location/v2/stores/nearby',
    headers: {
      'Accept': 'application/json'
    },
    data: {
      radius: 10,
      latlng: positionToStarbucksLatlng(position)
    },
    success: function(storesData) {
      console.log(storesData);
    }
  });
}, function(error) {
  console.log(error);
});

The Starbucks API payload looks like this:

{
    "paging": {
        "total": 99,
        "offset": 0,
        "limit": 10,
        "returned": 10
    },
    "stores": [
        {
            "distance": 0.2879,
            "store": {
                "id": "18315",
                "name": "QFC-Bellevue #874 (Bel-East)",
                ...
                "address": {
                  ...
                },
                "coordinates": {
                    "latitude": 47.596722,
                    "longitude": -122.148774
                },
                ... etc...

Draw an Empty Map

To create our map centered around the user's position, first we'll need to convert the position object to one which the Google Maps API uses, namely google.maps.LatLng

var positionToGoogleLatLng = function(position) {
  return new google.maps.LatLng(
    position.coords.latitude,
    position.coords.longitude
  );
};

Now, creating a Google map centered around that spot:

var drawStoresMap = function(position) {
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: positionToGoogleLatLng(position),
    zoom: 12
  });
};

Note: I've started with an arbitrary zoom level, which will work in a region like northern New Jersey, where there are a lot of Starbucks around. If your region doesn't have many, use a lower zoom level. In a real application, we would instruct the map to stretch or contract based on the density of nearby Starbucks locations, but that's beyond the scope of this tutorial.

Now we can add a call to this function to our navigator callback:

navigator.geolocation.getCurrentPosition(function(position) {
   $.ajax({
   // ...
    success: function(storesData) {
      drawStoresMap(position);
    }
  })
});

Draw Markers on the Map at Store Locations

Finally, we loop through the data returned by the Starbucks API to add markers to the map. Converting each store to a Google LatLng:

var storeToGoogleLatLng = function(store) {
  return new google.maps.LatLng(
    store.store.coordinates.latitude,
    store.store.coordinates.longitude
  );
};

...and create a marker for each store, with the name of the store as the title attribute for the hover:

var drawMarker = function(map, store) {
  var marker = new google.maps.Marker({
    map: map,
    position: storeToGoogleLatLng(store),
    title: store.store.name
  });
};

We add this to the map drawing function and loop through the stores:

var drawStoresMap = function(position, storesData) {
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: positionToGoogleLatLng(position),
    zoom: 12
  });

  for (var i = 0; i < storesData.stores.length; i++) {
    drawMarker(map, storesData.stores[i]);
  }
};

VoilĂ !

screenshot of completed map

You can see the entire page in this Gist.

Discover and read more posts from Yitz Schaffer
get started