Learning objectives:

At the end of the lesson, learners should be able to:

  • Understand how to use the cluster method in ArcGIS Maps SDK for JavaScript to improve map visualization
  • Understand how to add a legend to the map and customize it
  • Understand how to add a print widget to the map

Overview:

This tutorial will cover how to use the cluster method in ArcGIS Maps SDK for JavaScript to group markers that are too close together and improve map visualization. We will also learn how to use GeoJSON format data and add a legend to the map and customize it to display the layers and symbols. Lastly, we will learn how to add a print widget to the map and customize its behavior to allow users to print the map.

Requirements:

  • To follow along with this tutorial, you will need a ArcGIS for Developers account and an API key for the ArcGIS Maps SDK for JavaScript. You can obtain an API key by following the instructions provided by ArcGIS for Developers 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 or your  favorite browser.
  • Basic knowledge of HTML, CSS, and JavaScript.

Step 1: Set up the HTML document

The first thing we need to do is to create an HTML document that includes the necessary scripts and stylesheets. The code starts with the <!DOCTYPE html> declaration, which tells the browser that we are using HTML5.

Please note that in this tutorial we use the API key. For more details on how to get the API key please check the beginning lesson.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>ArcGIS Maps SDK for JavaScript - Intermediate </title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.20/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.20/"></script>
    <style>
        #viewDiv {
            height: 100vh;
        }
        #title {
            position: absolute;
            top: 10px;
            left: 100px;
            z-index: 1;
            background-color: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
        }
        #legend {
            position: absolute;
            bottom: 30px;
            left: 10px;
            z-index: 1;
            background-color: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <div id="viewDiv"></div>
    <div id="title">Kyrgyzstan earthquakes 2013-2023</div>
    <div id="legend"></div>
    <script src="https://js.arcgis.com/4.20/?api-key=YOUR_API_KEY"></script>
    <script>
        // Code will go here
    </script>
</body>
</html>

This code is a basic HTML file that includes links to the ArcGIS Maps SDK for JavaScript CSS and JavaScript libraries, as well as a map container and two div elements for the title and legend. It also includes a script tag for adding JavaScript code to create the map and display earthquake data. The api-key parameter in the ArcGIS API script tag needs to be replaced with a valid ArcGIS API key.

Step 2: Load the necessary modules and create a new map object

The next step is to load the necessary modules from the ArcGIS Maps SDK for JavaScript. We do this by using the require function, which takes an array of module names and a callback function as arguments. Also we create a map and view, which will be used to display the graphics layer we just created.

require([
    "esri/Map",
    "esri/views/MapView",
    "esri/layers/GeoJSONLayer",
    "esri/widgets/Legend",
    "esri/widgets/Expand",
    "esri/widgets/Print",
], function(Map, MapView, GeoJSONLayer, Legend, Expand, Print) {
    
    // Create a map with a basemap
    var map = new Map({
        basemap: "gray-vector"
    });
    
    // Create a view for the map
    var view = new MapView({
        container: "viewDiv",
        map: map,
        center: [74.766098, 41.204380], // Kyrgyzstan coordinates
        zoom: 7 // Zoom to Kyrgyzstan
    });

In this code, we are loading six modules using the require() function from the ArcGIS API for JavaScript library. The modules being loaded are:

  • esri/Map: This module is used to create a new map object with a specified basemap.
  • esri/views/MapView: This module is used to create a view object for the map. The view specifies the container where the map will be displayed, the map object to be displayed, and the initial center and zoom level of the map.
  • esri/layers/GeoJSONLayer: This module is used to create a GeoJSONLayer object, which can be used to display GeoJSON data on the map.
  • esri/widgets/Legend: This module is used to create a legend widget, which displays the symbology used in the layers on the map.
  • esri/widgets/Expand: This module is used to create an expand widget, which provides a way to collapse and expand a widget’s content.
  • esri/widgets/Print: This module is used to create a print widget, which allows the user to print the map.

The require() function also takes a callback function that is executed once all the required modules have been loaded. In this callback function, we create a new Map object with a “gray-vector” basemap and assign it to the map variable. Then we create a new MapView object with a container specified by the “viewDiv” element, the map object we just created, and an initial center and zoom level set to Kyrgyzstan’s coordinates.

Step 3: Define the cluster configuration object with settings for creating clusters of earthquake points on the map

Next step we create a cluster configuration object with the following properties:

  • type: “cluster”: Specifies that this is a cluster layer.
  • clusterRadius: “100px”: Sets the size of the cluster radius to 100 pixels.
  • popupTemplate: Configures the popup that appears when a user clicks on a cluster.
  • clusterMinSize: “24px”: Sets the minimum size of the cluster marker to 24 pixels.
  • clusterMaxSize: “60px”: Sets the maximum size of the cluster marker to 60 pixels.
  • symbol: Configures the symbol style of the cluster marker.
  • labelingInfo: Configures the label style of the cluster marker.
//Create the cluster configuration object and add it to the GeoJSONLayer object
            const clusterConfig = {
            type: "cluster",
            clusterRadius: "100px",
            popupTemplate: {
                title: "Cluster summary",
                content: "This cluster represents {cluster_count} earthquakes.",
                fieldInfos: [
                {
                    fieldName: "cluster_count",
                    format: {
                    places: 0,
                    digitSeparator: true
                    }
                }
                ]
            },
            clusterMinSize: "24px",
            clusterMaxSize: "60px",

            symbol: {
                type: "simple-marker",
                style: "circle",
                color: "#00619b",
                outline: {
                color: "rgba(0, 97, 155, 0.5)",
                width: 6
                }
            },

            labelingInfo: [
                {
                deconflictionStrategy: "none",
                labelExpressionInfo: {
                    expression: "Text($feature.cluster_count, '#,###')"
                },
                symbol: {
                    type: "text",
                    color: "#daf2de",
                    font: {
                    weight: "bold",
                    family: "Noto Sans",
                    size: "12px"
                    }
                },
                labelPlacement: "center-center"
                }
            ]
            };

Step 4: Fetching and Clustering Earthquake Data with GeoJSONLayer

In this step, a GeoJSONLayer object is created and configured to fetch earthquake data from the USGS Earthquake Catalog API, apply the cluster configuration object, and render the data points, which is then added to the map.

This code creates a GeoJSONLayer object with the following properties:

  • title: a title for the layer.
  • url: the URL to fetch the earthquake data from the USGS Earthquake Catalog API.
  • copyright: the copyright information.
  • featureReduction: a cluster configuration object to apply clustering to the data points and improve the performance of the layer.
  • popupTemplate: a template for the popups that appear when a user clicks on a data point. It displays information such as the magnitude, type, place, and time of the earthquake.
  • renderer: a symbol that defines how the data points should be displayed on the map. In this case, it’s a diamond-shaped marker with an outline and a specific color.

Finally, the code adds the earthquakes layer to the map using the map.add() method.

const layer = new GeoJSONLayer({
    title: "Earthquakes from the last decades 2013-2023",
    url: "https://earthquake.usgs.gov/fdsnws/event/1/query.geojson?starttime=2013-03-05%2000:00:00&endtime=2023-03-12%2023:59:59&maxlatitude=43.232&minlatitude=39.253&maxlongitude=80.354&minlongitude=69.28&minmagnitude=2.5&orderby=time",
    copyright: "USGS Earthquakes",

    featureReduction: clusterConfig,

    popupTemplate: {
        title: "Magnitude {mag} {type}",
        content: "Magnitude {mag} {type} hit {place} on {time}",
        fieldInfos: [
            {
                fieldName: "time",
                format: {
                    dateFormat: "short-date-short-time"
                }
            }
        ]
    },

    renderer: {
        type: "simple",
        symbol: {
            type: "simple-marker",
            size: 8,
            color: "#4b7e98",
            style: "diamond",
            outline: {
                color: "rgba(75, 126, 152, 1)",
                width: 1
            }
        }
    }
});

map.add(layer); //Add the earthquakes layer to the map

Step 5: Adding Cartographic Elements to a Map

1.After creating the GeoJSONLayer object, the code creates a Legend object that will display the magnitude of the earthquakes. The layerInfos parameter of the Legend object is set to an array with one object that specifies the layer (layer) and a title for the legend (title).

var legend = new Legend({
    view: view,
    layerInfos: [{
        layer: layer,
        title: "Magnitude"
    }]
});

The code then creates an Expand object for the legend and adds it to the top-left of the view.ui container.

var legendExpand = new Expand({
    view: view,
    content: legend,
    expanded: false
});
view.ui.add(legendExpand, "top-left");

2.Next, the code creates a Print widget that allows the user to print the map. The printServiceUrl parameter is set to a URL for the ArcGIS Online Printing Tools service.

var print = new Print({
    view: view,
    printServiceUrl: "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task"
});

3.The code then creates an Expand object for the print widget and adds it to the top-right of the view.ui container.

var printExpand = new Expand({
    view: view,
    content: print,
    expanded: false
});
view.ui.add(printExpand, "top-right");

With this code, you should be able to display a map of earthquakes that occurred between 2013 and 2023 in a specific region, with clustering, popups, and legends. The user can also print the map or expand the legend to view it more clearly.

Step 6: Final step. Save HTML

Finally, the code ends with an HTML element which specifies where the map will be displayed on the web page. Save the HTML file and open it in your favorite  web browser. Next you can find full code:

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>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>ArcGIS API for JavaScript - Intermediate </title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.20/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.20/"></script>
    <style>
        #viewDiv {
            height: 100vh;
        }
        #title {
            position: absolute;
            top: 10px;
            left: 100px;
            z-index: 1;
            background-color: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
        }
        #legend {
            position: absolute;
            bottom: 30px;
            left: 10px;
            z-index: 1;
            background-color: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <div id="viewDiv"></div>
    <div id="title">Kyrgyzstan earthquakes 2013-2023</div>
    <div id="legend"></div>
    <script src="https://js.arcgis.com/4.20/?api-key=de612aae9f904574bd7ad6cca38acdf1"></script>
    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/layers/GeoJSONLayer",
            "esri/widgets/Legend",
            "esri/widgets/Expand",
            "esri/widgets/Print",
        ], function(Map, MapView, GeoJSONLayer, Legend, Expand, Print) {
            
            // Create a map with a basemap
            var map = new Map({
                basemap: "gray-vector"
            });
            
            // Create a view for the map
            var view = new MapView({
                container: "viewDiv",
                map: map,
                center: [74.766098, 41.204380], // Kyrgyzstan coordinates
                zoom: 7 // Zoom to Kyrgyzstan
            });
            
            //Create the cluster configuration object and add it to the GeoJSONLayer object
            const clusterConfig = {
            type: "cluster",
            clusterRadius: "100px",
            popupTemplate: {
                title: "Cluster summary",
                content: "This cluster represents {cluster_count} earthquakes.",
                fieldInfos: [
                {
                    fieldName: "cluster_count",
                    format: {
                    places: 0,
                    digitSeparator: true
                    }
                }
                ]
            },
            clusterMinSize: "24px",
            clusterMaxSize: "60px",

            symbol: {
                type: "simple-marker",
                style: "circle",
                color: "#00619b",
                outline: {
                color: "rgba(0, 97, 155, 0.5)",
                width: 6
                }
            },

            labelingInfo: [
                {
                deconflictionStrategy: "none",
                labelExpressionInfo: {
                    expression: "Text($feature.cluster_count, '#,###')"
                },
                symbol: {
                    type: "text",
                    color: "#daf2de",
                    font: {
                    weight: "bold",
                    family: "Noto Sans",
                    size: "12px"
                    }
                },
                labelPlacement: "center-center"
                }
            ]
            };
                // Create a layer for the earthquakes data
                const layer = new GeoJSONLayer({
                title: "Earthquakes from the last decades 2013-2023",
                url: "https://earthquake.usgs.gov/fdsnws/event/1/query.geojson?starttime=2013-03-05%2000:00:00&endtime=2023-03-12%2023:59:59&maxlatitude=43.232&minlatitude=39.253&maxlongitude=80.354&minlongitude=69.28&minmagnitude=2.5&orderby=time",
                copyright: "USGS Earthquakes",

                featureReduction: clusterConfig,

                // popupTemplates can still be viewed on
                // individual features
                popupTemplate: {
                    title: "Magnitude {mag} {type}",
                    content: "Magnitude {mag} {type} hit {place} on {time}",
                    fieldInfos: [
                    {
                        fieldName: "time",
                        format: {
                        dateFormat: "short-date-short-time"
                        }
                    }
                    ]
                },
                renderer: {
                    type: "simple",
                    symbol: {
                    type: "simple-marker",
                    size: 8,
                    color: "#4b7e98",
                    style: "diamond",
                    outline: {
                        color: "rgba(75, 126, 152, 1)",
                        width: 1
                    }
                    }
                }
                });
                
            // Add the earthquakes layer to the map
            map.add(layer);
            
            // Create a legend for the earthquakes layer
            var legend = new Legend({
                view: view,
                layerInfos: [{
                    layer: layer,
                    title: "Magnitude"
                }]
            });
            
            // Add the legend to the view
            var legendExpand = new Expand({
                view: view,
                content: legend,
                expanded: false
            });
            view.ui.add(legendExpand, "top-left");
            
            // Create a print widget and add it to the view
            var print = new Print({
                view: view,
                printServiceUrl: "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task"
            });
            
            var printExpand = new Expand({
                view: view,
                content: print,
                expanded: false
            });
            view.ui.add(printExpand, "top-right");
        });
    </script>
</body>
</html>

Conclusion:

In this lesson, learners have been introduced to creating a GeoJSONLayer with a clustering feature in ArcGIS API for JavaScript, as well as adding a legend to the map view. Some of the key concepts covered from this lesson include creating a map with a basemap, creating a view for the map, creating a layer for the earthquakes data, and adding the earthquakes layer to the map. Learners have also learned about cluster configuration object and how it is added to the GeoJSONLayer object.

Some of the key concepts covered from this lesson include:

  • How to create a map using the ArcGIS Maps SDK for JavaScript
  • How to add layers to the map
  • How to configure feature reduction for large datasets
  • How do add widgets like a legend and an expand widget

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