Rendering a Google Map in a JavaScript Front-End: Part I

Installation and setup of the Google Maps Project and the Maps API

Luke Menard
Analytics Vidhya
7 min readSep 18, 2019

--

I am a new coder and current student at the Flatiron School, with a background in land conservation and spatial modeling. A primary motivation for learning software development was a desire to build my capacity to create novel, usable tools that assist the critical work of natural resource managers and conservationists on the ground.

As so much of my past work was map-based, I knew that I wanted one of my first projects as a coder to incorporate an interactive web map with a practical application. When posed with the challenge of creating Rails application with a JavaScript frontend, I decided to use the Google Maps JavaScript API to build a tool to help firefighters and foresters track wildfires and plan prescribed burns.

Project Setup on the Google Cloud Platform

Before beginning any development using the Google Maps API, I first needed to complete a few key tasks:

  1. Create a Google Maps project on the Google Cloud Platform
  2. Choose a suite of Google Maps products to apply to the project
  3. Get an API key
  4. Enable project billing

Creating a Google Cloud Project

I first created an account on the Google Cloud Platform. To then add a new project to my account, I navigated to the projects dropdown on the main page,

clicked the “New Project” button on the subsequent screen,

and gave the new project a name (with the option of assigning it to an organizational folder).

Choosing a Google Maps Product Suite

With a new project created, I then needed to think through what, specifically, I wanted that project to accomplish. I mapped out a clear user story — I wanted to populate a map with real-time wildfire point data and give the end-user the ability to navigate around the map and interact with that data. Additionally, I wanted the targeted end-user (e.g. wildfire fighters and foresters) to be able to draw persistent, editable polygons around each wildfire point to spatially represent the current extent of the fire. Finally, I wanted the map to automatically georeference to the user’s location upon rendering to make drawing accurate polygons simpler.

The Google Maps JavaScript API offers three distinct sets of products and tools that a developer can apply to a project in their Cloud Platform:

  1. Maps: give the developer the ability to add interactive maps to an application that include Street View imagery and 360-degree panoramas.
  2. Routes: allow your user to determine the most efficient path from one point to another. The Routes package also provides navigation and real-time traffic updates.
  3. Places: allows the user to find specific locations using phone numbers and addresses. The Places package includes additional APIs that provide the capacity to geocode addresses to specific coordinates and return the location of a device using cell tower and WiFi node data.

Upon creating a new project, I was prompted to select the set of tools that I wanted the project to access. Based on the user story and goals I set out, I decided the Maps and Places packages were both necessary.

Getting an API Key

To render a map in the application, I first needed to generate an API key specific to my Google Cloud account and project. To create a new API key, I navigated back to the Google Cloud Platform. Within the hamburger menu, I selected the “Credentials” option in the “APIs & Services” menu.

Choosing the “Create credentials” dropdown on the subsequent page and selecting “API key” generated a unique key that I saved for reference and utilized when building out the HTML for my application.

Enabling Project Billing

The Google Maps JavaScript API requires you to enter credit card information and acknowledge a billing policy before enabling the use of products in an application. Total monthly billing for a project is determined by both the Google Maps products utilized, as well as application usage. From the Google Maps Platform billing page:

• Usage is tracked for each Product SKU.

• A SKU is the combination of the Product API + the service or function called (for example, Places API — Place Details).

• A product may have multiple SKUs billed at different rates (for example, Places API — Place Details; Places API — Autocomplete — Per Request).

• SKU pricing is tiered, based on volume of use, with three tiers: 0–100,000; 100,001–500,000; 500,001+.

• Cost is calculated by SKU Usage x Price per each use.

Rendering the Map

Creating the File Structure

There are two critical files needed to render a map in the browser:

  1. index.html: dictates the basic structure and flow of the webpage, serves as the link to the Google Maps API by housing the API key, and initializes the map render via a callback function.
  2. index.js: houses the map initialization function and any operations to be performed on the rendering.

Building the HTML

I included the following components in my HTML file:

  1. At the top of the file, I declared the content of the document as HTML5:
<!DOCTYPE html>

2. In the head of the file, I described the document’s metadata and gave the application a title, as follows:

<html lang="en" dir="ltr">
<head>
<meta
charset="utf-8"
name="viewport"
content="width=device-width,
initial-scale=1,
shrink-to-fit=no">
<title>Wildfire Tracker</title>
</head>

3. I also create a related CSS stylesheet and used bootstrap, an open-source styling toolkit to enhance the look-and-feel of my app. I included links to both the stylesheet and the Boostrap CDN within the head tag.

4. The map itself is held within the body tags of the HTML file. After creating an h1 at the top of the page and a simple navigation bar using bootstrap, I created a placeholder div for the map itself.

<div class="map-container">
<div class = "map" id="map"></div>
</div>

5. At the base of the body, I linked to the related JavaScript file, index.js.

<script src="src/index.js" type="text/javascript"></script>

6. Finally, I included a call to a Google file that holds all of the symbols and definitions contained in the Google Maps JavaScript API. This script tag also passes the personalized API key I generated, as described above, to access the relevant data. Additionally, the “callback” keyword references a function within my JavaScript file that sets the attributes of the map to be rendered. “Async defer” specifies that the contents of the script tag should be executed when the rest of the page has finished parsing. Once the API is ready, it calls the function specified in the callback parameter (initMap, here)

<script
async defer src="https://maps.googleapis.com/maps/api/js?key={YOUR API KEY}
callback=initMap&libraries=drawing"
type="text/javascript">
</script>

Rendering the Map in JavaScript

The core functionality and styling of the map are held within an initialization function that is executed as the HTML file renders. First, a function is called and a new Google Maps element is created, as follows:

function initMap() {
let map = new google.maps.Map(
document.getElementById('map'){

This function also holds the desired styling for each element included on the map, as dictated by the Google Maps product(s) selected in the Google Cloud Platform upon project setup. Because I wanted bright wildfire point data to contrast well with the basemap, I chose dark mode styling, which I established, as follows:

styles: [
{elementType: 'geometry', stylers: [{color: '#242f3e'}]},
{elementType: 'labels.text.stroke', stylers: [{color: '#242f3e'}]},
{elementType: 'labels.text.fill', stylers: [{color: '#746855'}]},
{
featureType: 'administrative.locality',
elementType: 'labels.text.fill',
stylers: [{color: '#d59563'}]
},
{
featureType: 'poi',
elementType: 'labels.text.fill',
stylers: [{color: '#d59563'}]
},
{
featureType: 'poi.park',
elementType: 'geometry',
stylers: [{color: '#263c3f'}]
},
{
featureType: 'poi.park',
elementType: 'labels.text.fill',
stylers: [{color: '#6b9a76'}]
},
{
featureType: 'road',
elementType: 'geometry',
stylers: [{color: '#38414e'}]
},
{
featureType: 'road',
elementType: 'geometry.stroke',
stylers: [{color: '#212a37'}]
},
{
featureType: 'road',
elementType: 'labels.text.fill',
stylers: [{color: '#9ca5b3'}]
},
{
featureType: 'road.highway',
elementType: 'geometry',
stylers: [{color: '#746855'}]
},
{
featureType: 'road.highway',
elementType: 'geometry.stroke',
stylers: [{color: '#1f2835'}]
},
{
featureType: 'road.highway',
elementType: 'labels.text.fill',
stylers: [{color: '#f3d19c'}]
},
{
featureType: 'transit',
elementType: 'geometry',
stylers: [{color: '#2f3948'}]
},
{
featureType: 'transit.station',
elementType: 'labels.text.fill',
stylers: [{color: '#d59563'}]
},
{
featureType: 'water',
elementType: 'geometry',
stylers: [{color: '#17263c'}]
},
{
featureType: 'water',
elementType: 'labels.text.fill',
stylers: [{color: '#515c6d'}]
},
{
featureType: 'water',
elementType: 'labels.text.stroke',
stylers: [{color: '#17263c'}]
}
]
})

Within the same initialization function, I also gave my end-users the ability to access the Google Maps Drawing Manager and introduced geolocation to render the interface using the user’s location as map center.

In my next post, I’ll discuss rendering, persisting, and performing full CRUD actions on various types of data using the Google Maps JavaScript API and a Ruby on Rails backend.

--

--