Learning objectives:

  • Understand how to use the fundamental syntax of HTML and CSS to create a webpage, including the use of tags, attributes, and styles.
  • Understand how to incorporate Google Maps into their web applications and how to use its API to interact with the map and add markers, circles, and other visual elements.
  • Understand how to design and implement a legend on a map to help users understand the information being presented.
  • Understand how to process and visualize data, in this case, earthquake data, using JavaScript and Google Maps API to display the data on a map.

Overview:

By the end of this lesson, students will be able to create a web map using the Google Maps API and display earthquake data from a specific region and time period, with custom styling and a legend. Students will learn how to use JavaScript libraries such as jQuery to create interactive elements on their web maps, and how to work with CSS. Students will also learn how to add interactivity to their web maps by allowing users to update the displayed data based on date range selections.

Requirements:

  • To follow along with this tutorial, you will need a Google account and an API key for the Google Maps API. You can obtain an API key by following the instructions provided by Google or please visit beginner lesson page.
  • A code editor such as Visual Studio Code, Sublime Text, Notepad++ or your favorite code editor.
  • A web browser such as Google Chrome or Mozilla Firefox
  • Basic knowledge of HTML, CSS, and JavaScript

Step 1: HTML Markup

First there will be created an HTML document with embedded JavaScript and CSS code. The first section of the code defines the HTML document and its header. The title of the page is “Google Maps API – Advance”. The viewport meta tag ensures that the map is displayed at the correct size on different devices.

<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps API - Intermediate </title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
      // Your code will go here
  </head>
  <body>
      // Your code will go here
  </body>
</html>

This line includes the Google Maps API script. You will need to replace “YOUR_API_KEY” with an actual API key that you obtain from Google.

     <!-- Include Google Maps API script -->
        <script src="https://maps.googleapis.com/maps/api/js?key=YOURAPIKEY"></script>

This line includes the jQuery library, which is a popular JavaScript library that makes it easier to manipulate HTML documents and handle events. 

<!-- Include jQuery library -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- Include datepicker.js and datepicker.css files -->

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>

Moving on to the <body> section, there are three main elements defined inside the <div> container with the id attribute:  

  • The first one is a title for the web page, displayed in a banner with a blue background, white text color, bold font, and centered text alignment. It reads “EARTHQUAKES IN KYRGYZSTAN AND SURROUNDING AREA FROM 2010 TO NOW”.
  • The second element with id=”map” is a container that will hold the interactive map of the earthquakes in Kyrgyzstan and surrounding areas. Its dimensions are set to height: 100%; in the CSS code, which means it will take up the entire available vertical space of the web page.
  • The third element is another container with id=”map-container”. It is set to position: relative; which means any elements inside it can be positioned relative to this container.
</head>

  <body>
    <div id="map-container">
    <div id="title">EARTHQUAKES IN KYRGYZSTAN AND SURROUNDING AREA FROM 2010 TO NOW</div>
    <div id="map"></div>
          <!-- Add the legend to the HTML -->
      // Your code will go here
</head>

Next , there should be created the earthquake magnitude legend that will be displayed on the map. The legend is divided into four categories based on the magnitude of the earthquakes. Each category is represented by a colored circle with a specific color, and a label indicating the magnitude range on the Richter scale. The legend is created using HTML and CSS, with each category represented by a <div> element that contains a colored circle (<span> element with class “circle”) and a label (<span> element with class “legend-label”). The legend is positioned on the map using CSS properties such as position, top, and left.

<div id="legend1">
        <h5>Magnitude (Richter Scale)</h5>
      </div>

      <!-- Add the legend to the HTML -->
    <div id="legend2" style="margin-top: 0px">

          <!-- size of legends circle -->
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fee5d9; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px;"></span>
    <span class="legend-label" style="margin-left: 25px;"> > 4 </span>
    </div> 
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fcae91; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px;"></span>
    <span class="legend-label" style="margin-left: 25px;">   ≥ 4 and < 5</span>
    </div>
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fb6a4a; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px"></span>
    <span class="legend-label" style="margin-left: 25px;">  ≥ 5 and < 6</span>
    </div>
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #cb181d; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px"></span>
    <span class="legend-label" style="margin-left: 25px"> ≥ 6</span>  
    </div>

The code below creates a date range container in the HTML, which contains two input fields for the start and end dates of the earthquake data to be displayed on the map. The “for” attribute in each label is used to associate the label with its corresponding input field using the “id” attribute. The “name” attribute in each input field specifies the name of the input field, which can be used to retrieve its value in JavaScript. The “onclick” attribute in the “Update Map” button specifies the function to be executed when the button is clicked, which in this case is “updateMap()”. This function is expected to retrieve the start and end dates selected by the user from the input fields and update the map accordingly to display only the earthquakes that occurred within that date range.

    </div>
    <div id="date-range-container">
    <div>
      <label for="start-date">Start Date:</label>
      <input type="date" id="start-date" name="start-date">
      <label for="end-date">End Date:</label>
      <input type="date" id="end-date" name="end-date">
      <button onclick="updateMap()">Update Map</button>
    </div>

Step 2: CSS styling

The block of Cascading Style Sheets (CSS) code created to define the styling of a web page. The code defines various elements of the page, such as the map, legend, title, and date range container.

     <!-- the position of legend top left -->
    <style>
        #map {
          height: 100%;
        }
        html,
        body {
          height: 100%;
          margin: 0;
          padding: 0;
        }

        #title {
        font-family: Arial, sans-serif;
        background-color: #F7F7F7;
        color: #000000;
        font-size: 1.2em;
        font-weight: bold;
        text-align: center;
        padding: 10px;
        }   
        
        #legend1 {
        font-family: Arial, sans-serif;
        background-color: #F7F7F7;
        padding: 10px;
        margin: 0px;
        position: absolute;
        top: 200px;
        left: 10px;
        z-index: 1;
        }
        #legend2 {
          font-family: Arial, sans-serif;
          background-color: #F7F7F7;
          padding: 19px;
          margin-top: 0px;
          position: absolute;
          top: 270px;
          left: 10px;
          z-index: 1;
        }

      #legend h5 {
        margin-top: 10;
      }

      #map-container {
        position: relative;
        height: 100%;
        width: 100%;
        z-index: 0;
      }

      #date-range-container {
      position: absolute;
      top: 70px;
      left: 50%;
      transform: translateX(-50%);
      background-color: #F7F7F7;
      padding: 10px;
      border-radius: 5px;
    }

      #date-range-container label {
        margin-right: 5px;
      }
  </style>

Step 3: Initialize the Map

The JavaScript code block below defines a function initMap() and two variables map and circles. The initMap() function initializes and adds a Google Map to the webpage. It sets the coordinates of Kyrgyzstan as the center of the map, and specifies a zoom level of 6. The google.maps.Map() method is used to create the map object and specify its center and zoom level. The map variable is used to store a reference to this map object so that it can be used later to add circles to the map. The circles variable is initialized as an empty array. This array will be used to store references to the circle objects that are created on the map later.

    <script>
      var map;
      var circles = [];

      // Initialize and add the map
      function initMap() {
        // Set the coordinates of Kyrgyzstan
        var kyrgyzstan = {lat: 41.2044, lng: 74.7661};

        // Create the map centered on Kyrgyzstan
        map = new google.maps.Map(
          document.getElementById('map'), {zoom: 6, center: kyrgyzstan});

        // Add event listener for zoom change
        google.maps.event.addListener(map, 'zoom_changed', function() {
          updateCircleSizes();
        });
      }

The updateMap() function is defined to update the earthquake map based on the user’s selected start and end dates. The first thing the function does is remove any existing circles from the map. This is done by looping through the circles array and calling the setMap(null) method on each circle object. Next, a new empty array is assigned to the circles variable. The function then gets the start and end dates that the user has selected from the start-date and end-date input fields, respectively, using the getElementById() method. These dates are stored in the startDate and endDate variables.

      // Define the updateMap function
      function updateMap() {
        // Remove existing circles from the map
        circles.forEach(function(circle) {
          circle.setMap(null);
        });
        circles = [];

        // Get the start and end dates from the input fields
        var startDate = document.getElementById("start-date").value;
        var endDate = document.getElementById("end-date").value;

Step 3: Fetch Earthquakes Data

Variable called url created for URL string that will be used to retrieve earthquake data for Kyrgyzstan from the United States Geological Survey (USGS) API. The URL includes several parameters that are used to filter the results, including the start and end dates of the search, the minimum magnitude of earthquakes to include in the search (in this case, 2), and the maximum and minimum longitude and latitude values to search within the specified region. The startDate and endDate variables are retrieved from the start-date and end-date input fields in the HTML, respectively. These values are concatenated into the URL string using string concatenation (+) so that the URL includes the selected start and end dates for the earthquake search.

        // Get earthquake data for Kyrgyzstan from USGS
        var url = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=" +
        startDate +
        "&endtime=" +
        endDate +
        "&minmagnitude=2&maxlongitude=80&minlongitude=65&maxlatitude=43&minlatitude=39";

Next, the code block below fetches data from the US Geological Survey (USGS) website using the URL constructed in the previous code block. The response is in JSON format. The function then loops through each earthquake in the data and creates a circle on the map to represent it. The circle’s center is set to the earthquake’s latitude and longitude. The fill color is determined by calling the getFillColor() function, which is not shown in this code block. The fill opacity is set to 1.0, which means the circle will be completely filled in. The map variable is used to add the circle to the map. Finally, the push() method is used to add each circle to the circles array, which allows them to be removed from the map later if needed.

        fetch(url)
          .then((response) => response.json())
          .then((data) => {
            // Loop through each earthquake and add a circle to the map
            data.features.forEach(function (feature) {
              var magnitude = feature.properties.mag;
              var location = feature.geometry.coordinates;
              var latLng = new google.maps.LatLng(location[1], location[0]);

              // Extract additional information
              var place = feature.properties.place;
              var time = new Date(feature.properties.time);
              var region = feature.properties.region;
              var country = feature.properties.country;
              var city = feature.properties.city;
              var timezone = feature.properties.timezone;
        
              // Create a circle for the earthquake 
              var circle = new google.maps.Circle({
                center: latLng,
                strokeWeight: 0,
                fillColor: getFillColor(magnitude),
                fillOpacity: 1,
                map: map,
                radius: 10000}); 
               circles.push(circle);

This code block below is part of the data.features.forEach loop and is responsible for creating and adding an info window to each circle marker on the map. First, the code creates a string variable content that includes details about the earthquake such as its magnitude, place, time, and coordinates. Then, the code creates an instance of google.maps.InfoWindow with the content string as its content. Next, the code adds a click event listener to the circle marker that, when triggered, sets the position of the info window to the location of the clicked circle marker and opens the info window.

              // Create the content for the info window
              var content =
                "<strong>Magnitude:</strong> " + magnitude + "<br>" +
                "<strong>Place:</strong> " + place + "<br>" +
                "<strong>Time:</strong> " + time.toLocaleString() + "<br>" +
                "<strong>Latitude:</strong> " + location[1] + "<br>" +
                "<strong>Longitude:</strong> " + location[0];

              // Create an info window for the circle
              var infoWindow = new google.maps.InfoWindow({
                content: content
              });

              // Add a click event listener to open the info window
              circle.addListener('click', function (event) {
                infoWindow.setPosition(event.latLng);
                infoWindow.open(map);
              });
            });

            updateCircleSizes();
  });

}

            // Define the updateCircleSizes function
            function updateCircleSizes() {
              // Loop through each circle and update its radius
              circles.forEach(function (circle) {
                var zoom = map.getZoom();
                var radius = 10000 / Math.pow(2, zoom - 6);
                circle.setRadius(radius);
              });
            }

To set the fill color of a circle based on the magnitude of an earthquake the getFillColor function takes in a magnitude parameter. It creates an array of colors. Each color in the array corresponds to a certain range of magnitudes. It returns a color based on the magnitude parameter passed in. The return value is determined by checking the magnitude against certain ranges, and returning the color that corresponds to the range it falls within.

// Define a function to set the circle fill color based on magnitude
function getFillColor(magnitude) {
  var colors = ['#fee5d9','#fee5d9','#fcae91','#fb6a4a','#cb181d'];
  return magnitude >= 6 ? colors[4] :
         magnitude >= 5 ? colors[3] :
         magnitude >= 4 ? colors[2] : 
         magnitude > 4 ? colors[1] :
                          colors[0];
 
  }

Step 5: Final step. Save HTML

Save the HTML file and open it in a web browser to view the map.

Note: that the code also includes comments which explain what each section of code does. These comments are denoted by the // symbol.

<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps API - Advance</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">

     <!-- Include Google Maps API script -->
        <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD71t8Yy7exOo1BExQ9EqSJhLZ130JGlrw"></script>

    <!-- Include jQuery library -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

    <!-- Include datepicker.js and datepicker.css files -->

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
     <!-- the position of legend top left -->
    <style>
        #map {
          height: 100%;
        }
        html,
        body {
          height: 100%;
          margin: 0;
          padding: 0;
        }

        #title {
        font-family: Arial, sans-serif;
        background-color: #F7F7F7;
        color: #000000;
        font-size: 1.2em;
        font-weight: bold;
        text-align: center;
        padding: 10px;
        }   
        
        #legend1 {
        font-family: Arial, sans-serif;
        background-color: #F7F7F7;
        padding: 10px;
        margin: 0px;
        position: absolute;
        top: 200px;
        left: 10px;
        z-index: 1;
        }
        #legend2 {
          font-family: Arial, sans-serif;
          background-color: #F7F7F7;
          padding: 19px;
          margin-top: 0px;
          position: absolute;
          top: 270px;
          left: 10px;
          z-index: 1;
        }

      #legend h5 {
        margin-top: 10;
      }

      #map-container {
        position: relative;
        height: 100%;
        width: 100%;
        z-index: 0;
      }

      #date-range-container {
      position: absolute;
      top: 70px;
      left: 50%;
      transform: translateX(-50%);
      background-color: #F7F7F7;
      padding: 10px;
      border-radius: 5px;
    }

      #date-range-container label {
        margin-right: 5px;
      }

  </style>
  </head>
  <body>
    <div id="map-container">
    <div id="title">EARTHQUAKES IN KYRGYZSTAN AND SURROUNDING AREA FROM 2010 TO NOW</div>
    <div id="map"></div>
          <!-- Add the legend to the HTML -->
    <div id="legend1">
        <h5>Magnitude (Richter Scale)</h5>
      </div>
      <!-- Add the legend to the HTML -->
    <div id="legend2" style="margin-top: 0px">

          <!-- size of legends circle -->
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fee5d9; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px;"></span>
    <span class="legend-label" style="margin-left: 25px;"> > 4 </span>
    </div> 
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fcae91; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px;"></span>
    <span class="legend-label" style="margin-left: 25px;">   ≥ 4 and < 5</span>
    </div>
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #fb6a4a; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px"></span>
    <span class="legend-label" style="margin-left: 25px;">  ≥ 5 and < 6</span>
    </div>
    <div class="legend-item" style="display: flex; align-items: center; margin-bottom: 5px;">
    <span class="circle" style="background-color: #cb181d; width: 10px; height: 10px; border-radius: 50%; margin-left: 10px"></span>
    <span class="legend-label" style="margin-left: 25px"> ≥ 6</span>  
    </div>
    </div>
    <div id="date-range-container">
    <div>
      <label for="start-date">Start Date:</label>
      <input type="date" id="start-date" name="start-date">
      <label for="end-date">End Date:</label>
      <input type="date" id="end-date" name="end-date">
      <button onclick="updateMap()">Update Map</button>
    </div>
    <script>
      var map;
      var circles = [];

      // Initialize and add the map
      function initMap() {
        // Set the coordinates of Kyrgyzstan
        var kyrgyzstan = {lat: 41.2044, lng: 74.7661};

        // Create the map centered on Kyrgyzstan
        map = new google.maps.Map(
          document.getElementById('map'), {zoom: 6, center: kyrgyzstan});

        // Add event listener for zoom change
        google.maps.event.addListener(map, 'zoom_changed', function() {
          updateCircleSizes();
        });
      }


      // Define the updateMap function
      function updateMap() {
        // Remove existing circles from the map
        circles.forEach(function(circle) {
          circle.setMap(null);
        });
        circles = [];

        // Get the start and end dates from the input fields
        var startDate = document.getElementById("start-date").value;
        var endDate = document.getElementById("end-date").value;

        // Get earthquake data for Kyrgyzstan from USGS
        var url = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=" +
        startDate +
        "&endtime=" +
        endDate +
        "&minmagnitude=2&maxlongitude=80&minlongitude=65&maxlatitude=43&minlatitude=39";

        fetch(url)
          .then((response) => response.json())
          .then((data) => {
            // Loop through each earthquake and add a circle to the map
            data.features.forEach(function (feature) {
              var magnitude = feature.properties.mag;
              var location = feature.geometry.coordinates;
              var latLng = new google.maps.LatLng(location[1], location[0]);

              // Extract additional information
              var place = feature.properties.place;
              var time = new Date(feature.properties.time);
              var region = feature.properties.region;
              var country = feature.properties.country;
              var city = feature.properties.city;
              var timezone = feature.properties.timezone;
        
              // Create a circle for the earthquake 
              var circle = new google.maps.Circle({
                center: latLng,
                strokeWeight: 0,
                fillColor: getFillColor(magnitude),
                fillOpacity: 1,
                map: map,
                radius: 10000}); 

               circles.push(circle);
              

              // Create the content for the info window
              var content =
                "<strong>Magnitude:</strong> " + magnitude + "<br>" +
                "<strong>Place:</strong> " + place + "<br>" +
                "<strong>Time:</strong> " + time.toLocaleString() + "<br>" +
                "<strong>Latitude:</strong> " + location[1] + "<br>" +
                "<strong>Longitude:</strong> " + location[0];

              // Create an info window for the circle
              var infoWindow = new google.maps.InfoWindow({
                content: content
              });

              // Add a click event listener to open the info window
              circle.addListener('click', function (event) {
                infoWindow.setPosition(event.latLng);
                infoWindow.open(map);
              });
            });

            updateCircleSizes();
            });

            }

            // Define the updateCircleSizes function
            function updateCircleSizes() {
              // Loop through each circle and update its radius
              circles.forEach(function (circle) {
                var zoom = map.getZoom();
                var radius = 10000 / Math.pow(2, zoom - 6);
                circle.setRadius(radius);
              });
            }

            // Define a function to set the circle fill color based on magnitude
            function getFillColor(magnitude) {
            var colors = ['#fee5d9','#fee5d9','#fcae91','#fb6a4a','#cb181d'];
            return magnitude >= 6 ? colors[4] :
            magnitude >= 5 ? colors[3] :
            magnitude >= 4 ? colors[2] : 
            magnitude > 4 ? colors[1] :
                          colors[0];
 
            }
    </script>
  </body>
</html>

Conclusion:

This tutorial has equipped students with the skills to create interactive web maps using the Google Maps API. Throughout the lesson, students have learned how to incorporate earthquake data from a particular region and time frame into their web maps. They have also gained proficiency in applying custom styling and implementing a legend to enhance the visual representation of the data. Moreover, students have become proficient in utilizing JavaScript libraries like jQuery to add interactive elements to their web maps, allowing users to engage with the displayed information. Additionally, they have gained familiarity with CSS, enabling them to modify the appearance and layout of their web maps according to their preferences. Furthermore, this lesson has empowered students to enhance the interactivity of their web maps by enabling users to update the displayed data based on selected date ranges. This skill enables users to explore and analyze earthquake data within specific time periods, offering a more comprehensive understanding of seismic activities. By the end of this tutorial, students have acquired a robust set of skills and knowledge to create compelling and informative web maps. These skills can be applied to various domains, such as data visualization, environmental studies, and urban planning, allowing students to harness the power of web mapping technology to convey information effectively.

Some of the key concepts covered in this lesson include:

  • How to use the Google Maps API to create web maps.
  • How incoporate earthquake data from a specific region and time period into web maps.
  • How custom styling to web maps and creating a legend for data interpretation.
  • JavaScript Libraries (e.g., jQuery): Using JavaScript libraries like jQuery to add interactive elements to web maps.
  • How modify the visual aspects of web maps using CSS.
  • How add interactivity to web maps, allowing users to update displayed data based on selected date ranges.

To further explore and expand on the concepts covered in this lesson, learners can refer to the following resources: