In this codelab, you learn everything you need to get started using Google Maps Platform for the web. You 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.
In this codelab, you build a simple web app that does the following:
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!
In this Codelab, you'll use the following Google Maps Platform products:
To complete this codelab, you'll need the following accounts, services, and tools:
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. 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.
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 need to install dependencies for this codelab.
Before you begin this codelab, do the following to download the starter project template, as well as the complete solution code:
/starter
directory and includes the basic file structure you need to complete the codelab. Everything you need to work with is located in the /starter/src
directory.npm install
in the /starter
directory. This installs all of the needed dependencies listed in package.json
.npm start
in the directory.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? Okay, 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.
Start by loading the Maps JavaScript API.
If you have previous experience with the Maps JavaScript 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 dependencies are normally dynamically included from code. To accomplish the equivalent of the script
tag above from code, do the following:
/src/app.js
. This file is where you will do all of your work for this codelab.loadMapsJSAPI()
function, and declare variables for your Google Maps Platform API key and the URI for loading the Maps JavaScript API.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`;
}
runApp
callback.googleMapsAPIURI
variable, there is a callback=runApp
parameter. This declares the name of a function we want to be automatically executed once the Maps JavaScript API is fully loaded. For now, stub that out with a console.log
statement:function runApp() {
console.log('Maps JS API loaded');
}
script
tag.script
tag with the appropriate parameters. loadMapsJSAPI()
. This inserts a script
tag into the DOM, and loads the Maps JavaScript 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;
window
.script
tag, you need to add your callback directly to the DOM's window
object to make it accessible by the Maps JavaScript API. To do this, add this to loadMapsJSAPI()
: window.runApp = runApp;
script
tag to head.
script
tag to document.head
to load the Maps JavaScript API when the web page is loaded.document.head.appendChild(script);
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 Maps JavaScript 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. Take a look at how that's done by creating a new function called displayMap()
.
center
: sets the latitude and longitude for the center of the map.zoom
: sets the initial zoom level of the map.function displayMap() {
const mapOptions = {
center: { lat: -33.860664, lng: 151.208138 },
zoom: 14
};
}
div
where the map should be injected into the DOM.index.html
, you see that there's already a div
that looks like this:<div id="map"></div>
To tell the Maps JavaScript API this is where you want the map to be injected, use document.getElementById
to get its DOM reference:
const mapDiv = document.getElementById('map');
google.maps.Map
.google.maps.Map
, and pass in the mapDiv
and mapOptions
. Map
instance from this function so that you can do more with it later: const map = new google.maps.Map(mapDiv, mapOptions);
return map;
displayMap()
from the runApp()
callback function so that it is called once the Maps JavaScript 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.
addMarkers()
function, and declare a locations
object that has the following set of latitude/longitude points for popular tourist attractions in Sydney.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 }
}
}
google.maps.Marker
for each marker you want displayed.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.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! 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
. 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;
google.maps.Marker
is created, so now all you need to do is update your 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, you'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 because the Google Maps Platform team created a helpful, open-source utility library called MarkerClustererPlus
that does everything for you automatically. You can view the source for MarkerClustererPluson GitHub.
MarkerCluster
.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.app.js
file:import MarkerClusterer from '@google/markerclustererplus';
MarkerClusterer
.MarkerClusterer
../img/m
. Notice the image filenames are numbered sequentially with the same prefix: m1.png
, m2.png
, m3.png
, and so on. imagePath
property in the options for the marker clusterer, you simply provide the path and file prefix, and the marker clusterer automatically uses all files with that prefix and append a number to the end.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);
}
clusterMarkers()
from the runApp()
callback function. The marker clusters are automatically 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 automatically renumbers and resizes 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 Maps JavaScript 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.
addListener
, removeListener
, and more. 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 => {
});
});
}
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.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);
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 by 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 Maps JavaScript 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 an 800-meter (approximately half-mile) radius around a marker when it is clicked.
google.maps.Circle
.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;
}
drawCircle()
function you wrote above from the click listener callback in addPanToMarker()
, and pass it the map and location of the marker. 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.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 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.
In this codelab, you covered the basics of what you can do with the Maps JavaScript API. Next, try adding some of these features to the map:
To continue learning more ways you can work with Google Maps Platform on the web, check out these links: