1. Before You Begin
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.
What you'll build
In this codelab, you 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 recenters 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
2. 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:
- Maps JavaScript API
- MarkerClustererPlus open source marker clustering library
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, follow the Get Started with Google Maps Platform guide or watch the Getting Started with Google Maps Platform playlist to complete the following steps:
- Create a billing account.
- Create a project.
- Enable Google Maps Platform APIs and SDKs (listed in the previous section).
- Generate an API key.
3. Get Set Up
Set up Google Maps Platform
If you do not already have a Google Cloud Platform account and a project with billing enabled, please see the Getting Started with Google Maps Platform guide to create a billing account and a project.
- In the Cloud Console, click the project drop-down menu and select the project that you want to use for this codelab.
- Enable the Google Maps Platform APIs and SDKs required for this codelab in the Google Cloud Marketplace. To do so, follow the steps in this video or this documentation.
- Generate an API key in the Credentials page of Cloud Console. You can follow the steps in this video or this documentation. All requests to Google Maps Platform require an API key.
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 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:
- 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 need to complete the codelab. Everything you need to work with is located in the /starter/src
directory. 2. Once you download the starter project, run npm install
in the /starter
directory. This installs 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 compiles and runs the code you write locally. webpack-dev-server also automatically reloads your app in the browser any time 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.
4. Load the Maps JavaScript API
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.
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, you'll use the @googlemaps/js-api-loader module. The JS API Loader is already included in the dependencies of the project's package.json
file, so it was installed when you ran npm install
earlier.
To use the JS API Loader, do the following:
- Open
/src/app.js
. This file is where you will do all of your work for this codelab. - Import the
Loader
class from @googlemaps/js-api-loader.
Add the following to the top ofapp.js
:import { Loader } from '@googlemaps/js-api-loader';
- Create an
apiOptions
object.
TheLoader
class requires a JSON object that specifies various options for loading the Maps JavaScript API, including your Google Maps Platform API key, what version of the API you want to load, and any additional libraries provided by the Maps JS API you want to load. For the purposes of this codelab, you only need to specify the API key by appending the following toapp.js
:const apiOptions = { apiKey: "YOUR API KEY" }
- Create an instance of
Loader
and pass it yourapiOptions
.const loader = new Loader(apiOptions);
- Load the Maps JS API.
To load the API, callload()
on theLoader
instance. The JS API Loader returns a promise that resolves once the API is loaded and ready for use. Add the following stub to load the API and handle the promise:loader.load().then(() => { console.log('Maps JS API loaded'); });
If everything is successful you should see the console.log
statement in the browser console. Using Chrome, this additional window can be accessed at View -> Developer -> Javascript 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:
import { Loader } from '@googlemaps/js-api-loader';
const apiOptions = {
apiKey: "YOUR API KEY"
}
const loader = new Loader(apiOptions);
loader.load().then(() => {
console.log('Maps JS API Loaded');
});
Now that the Maps JavaScript API is loaded, you'll load the map in the next step.
5. Display a map
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()
.
- Define your map settings.
The Maps JavaScript 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.
function displayMap() { const mapOptions = { center: { lat: -33.860664, lng: 151.208138 }, zoom: 14 }; }
- Get the
div
where the map should be injected into the DOM.
Before you can display the map, you need to tell the Maps JavaScript API where you want it to be displayed in the page. If you take a quick look inindex.html
, you see that there's already adiv
that looks like this:
To tell the Maps JavaScript API this is where you want the map to be injected, use<div id="map"></div>
document.getElementById
to get its DOM reference:const mapDiv = document.getElementById('map');
- Create an instance of
google.maps.Map
.
To ask the Maps JavaScript API to create a new map that can be displayed, create an instance ofgoogle.maps.Map
, and pass in themapDiv
andmapOptions
. You also return theMap
instance from this function so that you can do more with it later:const map = new google.maps.Map(mapDiv, mapOptions); return map;
- Display the map!
Once you define all of the logic for creating your map instance, all that's left is to calldisplayMap()
from the JS API promise handler so that it is called once the Maps JavaScript API loads:loader.then(() => { 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');
const map = new google.maps.Map(mapDiv, mapOptions);
return map;
}
6. Cloud-based map styling (Optional)
You can customize the style of your map using Cloud-based map styling.
Create a Map ID
If you have not yet created a map ID with a map style associated to it, see the Map IDs guide to complete the following steps:
- Create a map ID.
- Associate a map ID to a map style.
Adding the Map ID to your app
To use the map ID you created, modify the displayMap
function in the app.js
file and pass your map ID in the mapId
property of the mapOptions
object.
app.js
function displayMap() {
const mapOptions = {
center: { lat: -33.860664, lng: 151.208138 },
zoom: 14,
mapId: 'YOUR_MAP_ID'
};
const mapDiv = document.getElementById('map');
return new google.maps.Map(mapDiv, mapOptions);
}
Once you've completed this, you should now see the style you selected on the map!
7. Add 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.
- Define an object for your marker locations.
To start, create a newaddMarkers()
function, and declare alocations
object that has the following set of latitude/longitude points for popular tourist attractions in Sydney.
Also, note that you need to pass yourMap
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 } } }
- Create an instance of
google.maps.Marker
for each marker you want displayed.
To create your markers, use the code below to iterate through thelocations
object using afor...in
loop, create a set of options for how each marker should be rendered, and then create an instance ofgoogle.maps.Marker
for each location.
Notice theicon
property ofmarkerOptions
. 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!
Theicon
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;
- Display the markers.
The Maps JavaScript API automatically creates and displays a marker whenever a new instance ofgoogle.maps.Marker
is created, so now all you need to do is update your JS API promise handler to calladdMarkers()
and pass it yourMap
instance:loader.then(() => { console.log('Maps JS API loaded'); 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.
8. Enable 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.
- Import the
MarkerCluster
.
For the template project for this codelab, theMarkerClustererPlus
utility library is already included in the dependencies declared in thepackage.json
file, so you already installed it when you rannpm install
at the beginning of this codelab.
To import the library, add the following to the top of yourapp.js
file:import MarkerClusterer from '@google/markerclustererplus';
- 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 ofMarkerClusterer
.
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
. Notice the image filenames are numbered sequentially with the same prefix:m1.png
,m2.png
,m3.png
, and so on.
When you set theimagePath
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.
Second, create a new instance ofMarkerClusterer
, and pass it the instance ofMap
where you want the marker clusters displayed and an array ofMarker
instances that you want clustered.function clusterMarkers(map, markers) { const clustererOptions = { imagePath: './img/m' } const markerCluster = new MarkerClusterer(map, markers, clustererOptions); }
- Display the marker clusters.
CallclusterMarkers()
from the JS API promise handler. The marker clusters are automatically added to the map when theMarkerClusterer
instance is created in the function call.loader.then(() => { 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.
9. Add 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.
- Set a click listener on your markers.
All of the objects in the Maps JavaScript API that support the event system implement a standard set of functions for handling user interaction, such asaddListener
,removeListener
, and more.
To add a click event listener to each marker, iterate themarkers
array and calladdListener
on the marker instance to attach a listener for theclick
event:function addPanToMarker(map, markers) { markers.map(marker => { marker.addListener('click', event => { }); }); }
- Pan to a marker when it is clicked on.
Theclick
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 theclick
event and use itsLatLng
object to get the latitude and longitude of the marker that was clicked.
Once you have that, simply pass that to theMap
instance's built-inpanTo()
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);
- Assign the click listeners.
CalladdPanToMarker()
from the JS API promise handler, and pass it your map and markers to execute the code and assign your click listeners.loader.then(() => { 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.
10. Draw on the map
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.
- Draw a circle with
google.maps.Circle
.
The drawing functions in the Maps JavaScript 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 ofgoogle.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; }
- 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 thedrawCircle()
function you wrote above from the click listener callback inaddPanToMarker()
, and pass it the map and location of the marker.
Notice how a conditional statement is also added that callscircle.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.
YouraddPanToMarker()
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:
11. Congratulations
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.
What's next?
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:
- 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: