Spotted a bug? Have a great idea? Help us make google.dev great!

Google Maps Platform 101: JavaScript

Abstract

In this codelab you'll learn everything you need to get started using Google Maps Platform for the web. You'll learn all the basics from getting set up to loading the Maps JavaScript API, displaying your first map, working with markers and marker clustering, drawing on the map, and handling user interaction.

What you'll build

In this codelab, you'll build a simple web app that does the following:

  • Loads the Maps JavaScript API
  • Displays a map centered on Sydney, Australia
  • Displays custom markers for popular attractions in Sydney
  • Implements marker clustering
  • Enables user interaction that re-centers and draws a circle on the map when a marker is clicked

What you'll learn

  • Getting started with Google Maps Platform
  • Loading the Maps JavaScript API dynamically from JavaScript code
  • Loading a map
  • Using markers, custom markers, and marker clustering
  • Working with the Maps JavaScript API event system to provide user interaction
  • Controlling the map dynamically
  • Drawing on the map

Prerequisites

You'll need to familiarize with the items below to complete this Codelab. If you are already familiar with working with Google Maps Platform, skip ahead to the Codelab!


Required Google Maps Platform Products

In this Codelab, you'll use the following Google Maps Platform products:

Other Requirements for this Codelab

To complete this codelab, you'll need the following accounts, services, and tools:

  • A Google Cloud Platform account with billing enabled
  • A Google Maps Platform API key with the Maps JavaScript API enabled
  • Basic knowledge of JavaScript, HTML, and CSS
  • Node.js installed on your computer
  • A text editor or IDE of your choice

Get started with Google Maps Platform

If you haven't used Google Maps Platform before, then follow the Get Started with Google Maps Platform guide or watch the Getting Started with Google Maps Platform playlist to complete the following steps:

  1. Create a billing account.
  2. Create a project.
  3. Enable Google Maps Platform APIs and SDKs.
  4. Generate an API key.

Set up Google Maps Platform

1. In the Cloud Console, click the project drop-down menu and select the project that you want to use for this codelab.


2. In the Google Cloud Marketplace, enable the Google Maps Platform APIs and SDKs

required for this codelab by following the steps in this video or this documentation.

3. On the Credentials page in the Cloud Console, generate an API key by following the steps in

this video or this documentation.

You need an API key to authenticate and bill all requests to Google Maps Platform.

Node.js Setup

If you do not already have it, go to https://nodejs.org/ to download and install the node.js runtime on your computer.

Node.js comes with the NPM package manager, which you will also need to install dependencies for this codelab.

Project Starter Template Setup

Before you begin this codelab, do the following to download the starter project template as well as the complete solution code:

  1. Download or fork the GitHub repo for this codelab at https://github.com/googlecodelabs/maps-platform-101-js.

    The starter project is located in the /starter directory and includes the basic file structure you'll need to complete the codelab. Everything you need to work with is located in the /starter/src directory.
  2. Once you've downloaded the starter project, run npm install in the /starter directory. This will install all of the needed dependencies listed in package.json.
  3. Once your dependencies are installed, run npm start in the directory.

    The starter project has been set up for you to use Webpack dev server, which will compile and run locally the code you'll be writing. Webpack dev server will also automatically reload your app in the browser anytime you make code changes.

If you'd like to see the full solution code running, you can complete the setup steps above in the /solution directory.

Before you begin, please make sure you follow the steps in Getting Set Up. All done? Ok, time to build your first web app using Google Maps Platform!

The foundation of using Google Maps Platform for the web is the Maps JavaScript API. This API provides a JavaScript interface for using all of the features of Google Maps Platform, including the map, markers, drawing tools, and other Google Maps Platform services, such as Places.

Let's start by loading the Maps JavaScript API.

If you have previous experience with the JS API, you may be familiar with loading it by inserting a script tag into an HTML file like this:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">

This is still a perfectly valid way of loading the API, but in modern JavaScript we often prefer to dynamically include our dependencies from code, so let's take a look at how to do the equivalent of the script tag above completely from code.

  1. Open /src/app.js. This file is where you will do all of your work for this codelab.
  2. Create a loadMapsJSAPI() function, and declare variables for your Google Maps Platform API key and the URI for loading the JS API.

    Note that you'll need to replace YOUR API KEY in the example code below with your actual API key.
function loadMapsJSAPI() {
  const googleMapsAPIKey = 'YOUR API KEY';
  const googleMapsAPIURI = `https://maps.googleapis.com/maps/api/js?key=${googleMapsAPIKey}&callback=runApp`;
}
  1. Create a stub for the runApp callback.

    Notice that in the googleMapsAPIURI variable above, there is a callback=runApp parameter. This declares the name of a function we want to be automatically executed once the JS API is fully loaded. For now, let's stub that out with a console.log statement:
function runApp() {
  console.log('Maps JS API loaded'); 
}
  1. Create the script tag.

    Next, dynamically create the script tag with the appropriate parameters.

    To do this, add the below code snippet to loadMapsJSAPI(). This will insert a script tag into the DOM, and load the JS API asynchronously in the same way that it would if you had hardcoded it directly in index.html.
const script = document.createElement('script');
script.src = googleMapsAPIURI;
script.defer = true;
script.async = true;
  1. Attach your callback function to window.

    Since you are dynamically loading the JS API, rather than inline in an HTML file using the script tag, you need to add your callback directly to the DOM's window object to make it accessible by the JS API. To do this, add this to loadMapsJSAPI():
  window.runApp = runApp;
  1. Append the script tag to head.
    Now all you have to do is append the script tag to document.head to load the JS API when the webpage is loaded.
document.head.appendChild(script);
  1. Load the Maps JS API

    To execute the loading of the JS API, call loadMapsJSAPI() at the top of app.js:
loadMapsJSAPI();

If everything is successful you should see the console.log statement from the runApp() callback in the browser console:

To recap, you've now dynamically loaded the Maps JavaScript API from code, and defined the callback function that is executed once the JS API is done loading.

Your app.js file should look something like this:

loadMapsJSAPI();
function runApp() {
  console.log('Maps JS API loaded'); 
}

function loadMapsJSAPI(googleMapsAPIKey) {
  const googleMapsAPIKey = 'YOUR API KEY';
  const googleMapsAPIURI = `https://maps.googleapis.com/maps/api/js?key=${googleMapsAPIKey}&callback=runApp`;
  
  const script = document.createElement('script');
  script.src = googleMapsAPIURI;
  script.defer = true;
  script.async = true;
  
  window.runApp = runApp;
  
  document.head.appendChild(script);
}

Now that the Maps JavaScript API is loaded, you'll load the map in the next step.

Time to display your first map!

The most commonly used part of the Maps JavaScript API is google.maps.Map, which is the class that allows us to create and manipulate map instances. Let's take a look at how that's done by creating a new function called displayMap().

  1. Define your map settings.

    The JS API supports a variety of different settings for the map, but only two are required

    - center: sets the latitude and longitude for the center of the map.
    - zoom: sets the initial zoom level of the map.

    Use the code below to center the map on Sydney, Australia, and give it a zoom level of 14, which is just the right zoom level to show the city center.
function displayMap() {
  const mapOptions = {
    center: { lat: -33.860664, lng: 151.208138 },
    zoom: 14
  };
}
  1. Get the div where the map should be injected into the DOM.

    Before you can display the map, you'll need to tell the JS API where you want it to be displayed in the page. If you take a quick look in index.html you'll see that there's already a div that looks like this:

    <div id="map"></div>

    To tell the JS API this is where you want the map to be injected, use document.getElementById to get its DOM reference:
const mapDiv = document.getElementById('map');
  1. Create an instance of google.maps.Map.

    To ask the Maps JS API to create a new map that can be displayed, create an instance of google.maps.Map and pass in the mapDiv and mapOptions.

    You'll also return the Map instance from this function so that you can do more with it later:
  const map = new google.maps.Map(mapDiv, mapOptions);
  return map;
  1. Display the map!

    Once you've defined all of the logic for creating your map instance, all that's left is to call displayMap() from the runApp() callback function, so that it is called once the JS API loads:
function runApp() {
  console.log('Maps JS API loaded');
  const map = displayMap(); 
}

You should now see a beautiful map of Sydney in your browser!

To recap, in this step you defined display options for the map, created a new map instance, and injected it into the DOM.

Your displayMap() function should look something like this:

function displayMap() {
  const mapOptions = {
    center: { lat: -33.860664, lng: 151.208138 },
    zoom: 14
  };
  const mapDiv = document.getElementById('map');
  return new google.maps.Map(mapDiv, mapOptions);
}

Next, you'll add some markers to the map.

There's lots of things developers do with the Maps JavaScript API, but putting markers on the map is definitely the most popular. Markers allow you to show specific points on the map, and are a common UI element for handling user interaction. If you've used Google Maps before, then you're probably familiar with the default marker, which looks like this:

In this step, you'll use google.maps.Marker to put markers on the map.

  1. Define an object for your marker locations.

    To start, create a new addMarkers() function, and declare a locations object that has the following set of latitude/longitude points for popular tourist attractions in Sydney.

    Also note that you'll need to pass your Map instance to the function. You'll use this later when you create your marker instances.
function addMarkers(map) {
  const locations = {
    operaHouse: { lat: -33.8567844, lng: 151.213108 },
    tarongaZoo: { lat: -33.8472767, lng: 151.2188164 },
    manlyBeach: { lat: -33.8209738, lng: 151.2563253 },
    hyderPark: { lat: -33.8690081, lng: 151.2052393 },
    theRocks: { lat: -33.8587568, lng: 151.2058246 },
    circularQuay: { lat: -33.858761, lng: 151.2055688 },
    harbourBridge: { lat: -33.852228, lng: 151.2038374 },
    kingsCross: { lat: -33.8737375, lng: 151.222569 },
    botanicGardens: { lat: -33.864167, lng: 151.216387 },
    museumOfSydney: { lat: -33.8636005, lng: 151.2092542 },
    maritimeMuseum: { lat: -33.869395, lng: 151.198648 },
    kingStreetWharf: { lat: -33.8665445, lng: 151.1989808 },
    aquarium: { lat: -33.869627, lng: 151.202146 },
    darlingHarbour: { lat: -33.87488, lng: 151.1987113 },
    barangaroo: { lat: - 33.8605523, lng: 151.1972205 }
  }
}
  1. Create an instance of google.maps.Marker for each marker you want displayed.

    To create your markers, use the code below to iterate through the locations object using a for...in loop, create a set of options for how each marker should be rendered, and then create an instance of google.maps.Marker for each location.

    Notice the icon property of markerOptions. Remember the default map pin from earlier? Did you know you can also customize the pin to be any image you want? Well, you can!

    The icon property allows you to provide the path to any image file you want to use as a custom marker. If you started this codelab using our project template, then an image is already included for you in /src/images.

    Notice also that you need to store your marker instances in an array and return them from the function, so that they can be used later.
  const markers = [];
  for (const location in locations) {
    const markerOptions = {
      map: map,
      position: locations[location],
      icon: './img/custom_pin.png'
    }
    const marker = new google.maps.Marker(markerOptions);
    markers.push(marker);
  }
  return markers;
  1. Display the markers.

    The Maps JavaScript API will automatically create and display a marker whenever a new instance of google.maps.Marker is created, so now all you need to do is update our runApp() callback function to call addMarkers() and pass it your Map instance:
function runApp() {
  const map = displayMap(); 
  const markers = addMarkers(map);
}

You should now see custom markers on the map:

To recap, in this step you defined a set of marker locations, and created an instance of google.maps.Marker with a custom marker icon for each location.

Your addMarkers() function should look something like this:

function addMarkers(map) {
  const locations = {
    operaHouse: { lat: -33.8567844, lng: 151.213108 },
    tarongaZoo: { lat: -33.8472767, lng: 151.2188164 },
    manlyBeach: { lat: -33.8209738, lng: 151.2563253 },
    hyderPark: { lat: -33.8690081, lng: 151.2052393 },
    theRocks: { lat: -33.8587568, lng: 151.2058246 },
    circularQuay: { lat: -33.858761, lng: 151.2055688 },
    harbourBridge: { lat: -33.852228, lng: 151.2038374 },
    kingsCross: { lat: -33.8737375, lng: 151.222569 },
    botanicGardens: { lat: -33.864167, lng: 151.216387 },
    museumOfSydney: { lat: -33.8636005, lng: 151.2092542 },
    maritimeMuseum: { lat: -33.869395, lng: 151.198648 },
    kingStreetWharf: { lat: -33.8665445, lng: 151.1989808 },
    aquarium: { lat: -33.869627, lng: 151.202146 },
    darlingHarbour: { lat: -33.87488, lng: 151.1987113 },
    barangaroo: { lat: - 33.8605523, lng: 151.1972205 }
  }
  const markers = [];
  for (const location in locations) {
    const markerOptions = {
      map: map,
      position: locations[location],
      icon: './img/custom_pin.png'
    }
    const marker = new google.maps.Marker(markerOptions);
    markers.push(marker);
  }
  return markers;
}

In the next step, we'll look at how to improve the user experience of markers using marker clustering.

When using a lot of markers or markers that are in close proximity to one another, you may encounter an issue where the markers overlap or appear too crowded together, which causes a bad user experience. For example, after creating the markers in the last step, you may have noticed this:

This is where marker clustering comes in. Marker clustering is another commonly implemented feature, which groups nearby markers into a single icon that changes depending on the zoom level, like this:



The algorithm for marker clustering divides the visible area of the map into a grid, then clusters icons that are in the same cell. Luckily you don't have to worry about any of that, since the Google Maps Platform team has created a helpful, open-source utility library called MarkerClustererPlus that does everything for you automatically. You can view the source for MarkerClustererPlus on GitHub.

  1. Import the MarkerCluster.

    For the template project for this codelab, the MarkerClustererPlus utility library is already included in the dependencies declared in the package.json file, so you already installed it when you ran npm install at the beginning of this codelab.

    To import the library, add the following to the top of your app.js file:
import MarkerClusterer from '@google/markerclustererplus';
  1. Create a new instance of MarkerClusterer.

    To create marker clusters, you need to do two things: provide the icons you want to use for your marker clusters, and create a new instance of MarkerClusterer.

    First, declare an object that specifies the path to the icons you want to use. In the template project, there are already a set of images saved in ./img/m. You'll notice the image file names are numbered sequentially with the same prefix: m1.png, m2.png, m3.png, and so on.

    When you set the imagePath property in the options for the marker clusterer, you simply provide the path and file prefix, and the marker clusterer will automatically use all files with that prefix and append a number to the end.

    Second, create a new instance of MarkerClusterer and pass it the instance of Map where you want the marker clusters displayed, and an array of Marker instances that you want clustered.
function clusterMarkers(map, markers) {
  const clustererOptions = { imagePath: './img/m' }
  const markerCluster = new MarkerClusterer(map, markers, clustererOptions);
}
  1. Display the marker clusters.

    Call clusterMarkers() from the runApp() callback function. The marker clusters will automatically be added to the map when the MarkerClusterer instance is created in the function call.
function runApp() {
  console.log('Maps JS API loaded');
  const map = displayMap(); 
  const markers = addMarkers(map);
  clusterMarkers(map, markers);
}

You should now see a couple marker clusters on your map.

Notice that if you zoom in or out, MarkerClustererPlus will automatically renumber and resize the clusters for you. You can also click on any marker cluster icon to zoom in and see all of the markers included in that cluster.

To recap, in this step you imported the open-source MarkerClustererPlus utility library, and used it to create an instance of MarkerClusterer that automatically clustered the markers you created in the previous step.

Your clusterMarkers() function should look something like this:

function clusterMarkers(map, markers) {
  const clustererOptions = { imagePath: './img/m' }
  const markerCluster = new MarkerClusterer(map, markers, clustererOptions);
}

Next, you'll learn how to handle user interaction.

Now you have a great looking map that displays some of Sydney's most popular tourist destinations. In this step, you'll add some additional handling of user interactions using the event system of the Maps JavaScript API to further improve the user experience of your map.

The JS API provides a comprehensive event system that uses JavaScript event handlers to allow you to handle various user interactions in code. For example, you can create event listeners to trigger code execution for interactions like the user clicking on the map and markers, panning the view of the map, zooming in and out, and more.

In this step, you'll add a click listener to your markers, and then programmatically make the map pan to put the marker the user clicked at the center of the map.

  1. Set a click listener on your markers.

    All of the objects in the JS API that support the event system implement a standard set of functions for handling user interaction such as addListener, removeListener, and more.

    To add a click event listener to each marker, iterate the markers array and call addListener on the marker instance to attach a listener for the click event:
function addPanToMarker(map, markers) {
  markers.map(marker => {
    marker.addListener('click', event => {
  
    });
  });
}
  1. Pan to a marker when it is clicked on.

    The click event is triggered whenever a user clicks or taps on a marker, and returns an event as a JSON object with information about the UI element that was clicked. To improve the user experience of the map, you can handle the click event and use its LatLng object to get the latitude and longitude of the marker that was clicked.

    Once you have that, simply pass that to the Map instance's built-in panTo() function to have the map smoothly pan to recenter on the clicked marker by adding the following in the callback function of the event handler:
const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
map.panTo(location);
  1. Assign the click listeners.

    Call addPanToMarker() from runApp() and pass it your map and markers to execute the code and assign your click listeners.
function runApp() {
  console.log('Maps JS API loaded');
  const map = displayMap(); 
  const markers = addMarkers(map);
  clusterMarkers(map, markers);
  addPanToMarker(map, markers);
}

Now go to the browser and click on your markers. You should see the map automatically pan to recenter when a marker is clicked.

To recap, in this step, you used the event system of the Maps JavaScript API to assign a click listener to all of the markers on the map, retrieved the latitude and longitude of the marker from the fired click event, and used that to recenter the map whenever a marker is clicked.

Your addPanToMarker() function should look something like this:

function addPanToMarker(map, markers) {
  markers = markers.map(marker => {
    marker.addListener('click', event => {
      const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
      map.panTo(location);
    });
  });
  return markers;
}

Only one more step to go! Next, you'll further improve the user experience of the map using the drawing features of the Maps JavaScript API.

So far, you've created a map of Sydney that shows markers for popular tourist destinations, and handles the user interaction. For the last step of this codelab, you'll use the drawing features of the Maps JavaScript API to add an additional useful feature to your map experience.

Imagine that this map is going to be used by users that want to explore the city of Sydney. A useful feature would be to visualize a radius around a marker when it is clicked. This would allow the user to easily understand what other destinations are within an easy walking distance of the clicked marker.

The JS API includes a set of functions for drawing shapes on the map, such as squares, polygons, lines, and circles. Next, you'll render a circle to show a 800 meter (approximately half mile) radius around a marker when it is clicked.

  1. Draw a circle with google.maps.Circle

    The drawing functions in the JS API give you a wide variety of options for how a drawn object appears on the map. To render a circular radius, declare a set of options for a circle, such as color, stroke weight, where the circle should be centered and its radius, then create a new instance of google.maps.Circle to create a new circle:
function drawCircle(map, location) {
  const circleOptions = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 1,
    map: map,
    center: location,
    radius: 800
  }
  const circle = new google.maps.Circle(circleOptions);
  return circle;
}
  1. Draw the circle when a marker is clicked.

    To draw the circle when the user clicks on a marker, all you need to do is call the drawCircle() function you wrote above from the click listener callback in addPanToMarker() and pass it the map and location of the marker.

    Notice how a conditional statement is also added that calls circle.setMap(null). This removes the previously rendered circle from the map if the user clicks another marker, so that you don't end up with a map covered in circles as your user explores the map.

    Your addPanToMarker() function should look something like this:
function addPanToMarker(map, markers) {
  let circle;
  markers.map(marker => {
    marker.addListener('click', event => {
      const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
      map.panTo(location);
      if (circle) {
        circle.setMap(null);
      }
      circle = drawCircle(map, location);
    });
  });
}

All done! Go to your browser, and click on one of the markers. You should see a circular radius rendered around it:

You've successfully built your first web app using Google Maps Platform, including loading the Maps JavaScript API, loading a map, working with markers, controlling and drawing on the map, and adding user interaction.

To see the completed code, check out the finished project in the /solutions directory.

What's next?

In this codelab, we've covered only the basics of what you can do with the Maps JavaScript API. Next, try adding some of these features to the map:

  • Change the map type to display satellite, hybrid, and terrain maps.
  • Enable localization to load the map in different languages.
  • Customize other user interactions like zoom and map controls.
  • Add info windows to display information when markers are clicked.
  • Check out the additional libraries available for the Maps JavaScript API that enable additional functionality, such as Places, drawing, and visualization.

To continue learning more ways you can work with Google Maps Platform on the web, check out these links: