javascriptwidgetarcgisarcgis-js-api

My Measurement Widget in ArcGIS Javascript API does not work


I tried to merge two of the ArcGis Javascript API widgets in sandbox and those are the basemap gallery and the measurement, however, the measurement widget does not work. The measurement widget does not function in the sense that i am simply unable to measure on the map. Cannot select any points or I do not see any lines come up. What could the problem be and how do I go about fixing it?

    <html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1, maximum-scale=1,user-scalable=no"
    />
    <title>
      BasemapGallery widget | Sample | ArcGIS Maps SDK for JavaScript 4.26
    </title>
    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.26/esri/themes/light/main.css"
    />
    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>
    <script src="https://js.arcgis.com/4.26/"></script>
    <script>
      require([
        "esri/Map",
        "esri/views/SceneView",
        "esri/widgets/Expand",
        "esri/widgets/BasemapGallery",
        "esri/widgets/DistanceMeasurement2D",
        "esri/widgets/AreaMeasurement2D"
      ], (Map, SceneView, Expand, BasemapGallery, DistanceMeasurement2D, AreaMeasurement2D) => {
        const map = new Map({
          basemap: "topo-vector"
        });

        const view = new SceneView({
          container: "viewDiv",
          map: map,
          center: [-77.2627, 18.0927],
          zoom: 10
        });

         const basemapGallery = new BasemapGallery({
              view: view,
            });
    
            // Create an Expand instance and set the content
            // property to the DOM node of the basemap gallery widget
            // Use an Esri icon font to represent the content inside
            // of the Expand widget
    
            const bgExpand = new Expand({
              view: view,
              content: basemapGallery
            });
    
            // close the expand whenever a basemap is selected
            basemapGallery.watch("activeBasemap", () => {
              const mobileSize =
                view.heightBreakpoint === "xsmall" ||
                view.widthBreakpoint === "xsmall";
    
              if (mobileSize) {
                bgExpand.collapse();
              }
            });
    
            // Add the expand instance to the ui
    
            view.ui.add(bgExpand, "top-left");
            
            
            // add the toolbar for the measurement widgets
        view.ui.add("topbar", "top-right");

        document
          .getElementById("distanceButton")
          .addEventListener("click", function () {
            setActiveWidget(null);
            if (!this.classList.contains("active")) {
              setActiveWidget("distance");
            } else {
              setActiveButton(null);
            }
          });

        document
          .getElementById("areaButton")
          .addEventListener("click", function () {
            setActiveWidget(null);
            if (!this.classList.contains("active")) {
              setActiveWidget("area");
            } else {
              setActiveButton(null);
            }
          });

        function setActiveWidget(type) {
          switch (type) {
            case "distance":
              activeWidget = new DistanceMeasurement2D({
                view: view
              });

              // skip the initial 'new measurement' button
              activeWidget.viewModel.start();

              view.ui.add(activeWidget, "top-right");
              setActiveButton(document.getElementById("distanceButton"));
              break;
            case "area":
              activeWidget = new AreaMeasurement2D({
                view: view
              });

              // skip the initial 'new measurement' button
              activeWidget.viewModel.start();

              view.ui.add(activeWidget, "top-right");
              setActiveButton(document.getElementById("areaButton"));
              break;
            case null:
              if (activeWidget) {
                view.ui.remove(activeWidget);
                activeWidget.destroy();
                activeWidget = null;
              }
              break;
          }
        }

        function setActiveButton(selectedButton) {
          // focus the view to activate keyboard shortcuts for sketching
          view.focus();
          let elements = document.getElementsByClassName("active");
          for (let i = 0; i < elements.length; i++) {
            elements[i].classList.remove("active");
          }
          if (selectedButton) {
            selectedButton.classList.add("active");
          }
        }
        
        
             
      });
    </script>
  </head>
  <body>
    <div id="viewDiv"></div>
    <div id="topbar">
      <button
        class="action-button esri-icon-measure-line"
        id="distanceButton"
        type="button"
        title="Measure distance between two or more points"
      ></button>
      <button
        class="action-button esri-icon-measure-area"
        id="areaButton"
        type="button"
        title="Measure area"
      ></button>
    </div>
  </body>
</html>

Solution

  • You have two problems in your code,

    1. You were missing the declaration of activeWidget variable
    2. The widgets to measure in two dimensions are only supported on MapView, which is the view for two dimensions

    Here is the fixed code,

    <html lang="en">
    
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
        <title>
            BasemapGallery widget | Sample | ArcGIS Maps SDK for JavaScript 4.26
        </title>
        <link rel="stylesheet" href="https://js.arcgis.com/4.26/esri/themes/light/main.css" />
        <style>
            html,
            body,
            #viewDiv {
                padding: 0;
                margin: 0;
                height: 100%;
                width: 100%;
            }
        </style>
        <script src="https://js.arcgis.com/4.26/"></script>
        <script>
            require([
                "esri/Map",
                "esri/views/MapView",
                "esri/widgets/Expand",
                "esri/widgets/BasemapGallery",
                "esri/widgets/DistanceMeasurement2D",
                "esri/widgets/AreaMeasurement2D"
            ], (Map, MapView, Expand, BasemapGallery, DistanceMeasurement2D, AreaMeasurement2D) => {
                let activeWidget = null; // <- YOU WERE MISSING
    
                const map = new Map({
                    basemap: "topo-vector"
                });
    
                const view = new MapView({
                    container: "viewDiv",
                    map: map,
                    center: [-77.2627, 18.0927],
                    zoom: 10
                });
    
                const basemapGallery = new BasemapGallery({
                    view: view,
                });
    
                // Create an Expand instance and set the content
                // property to the DOM node of the basemap gallery widget
                // Use an Esri icon font to represent the content inside
                // of the Expand widget
    
                const bgExpand = new Expand({
                    view: view,
                    content: basemapGallery
                });
    
                // close the expand whenever a basemap is selected
                basemapGallery.watch("activeBasemap", () => {
                    const mobileSize =
                        view.heightBreakpoint === "xsmall" ||
                        view.widthBreakpoint === "xsmall";
    
                    if (mobileSize) {
                        bgExpand.collapse();
                    }
                });
    
                // Add the expand instance to the ui
    
                view.ui.add(bgExpand, "top-left");
    
    
                // add the toolbar for the measurement widgets
                view.ui.add("topbar", "top-right");
    
                document
                    .getElementById("distanceButton")
                    .addEventListener("click", function () {
                        setActiveWidget(null);
                        if (!this.classList.contains("active")) {
                            setActiveWidget("distance");
                        } else {
                            setActiveButton(null);
                        }
                    });
    
                document
                    .getElementById("areaButton")
                    .addEventListener("click", function () {
                        setActiveWidget(null);
                        if (!this.classList.contains("active")) {
                            setActiveWidget("area");
                        } else {
                            setActiveButton(null);
                        }
                    });
    
                function setActiveWidget(type) {
                    switch (type) {
                        case "distance":
                            activeWidget = new DistanceMeasurement2D({
                                view: view
                            });
    
                            // skip the initial 'new measurement' button
                            activeWidget.viewModel.start();
    
                            view.ui.add(activeWidget, "top-right");
                            setActiveButton(document.getElementById("distanceButton"));
                            break;
                        case "area":
                            activeWidget = new AreaMeasurement2D({
                                view: view
                            });
    
                            // skip the initial 'new measurement' button
                            activeWidget.viewModel.start();
    
                            view.ui.add(activeWidget, "top-right");
                            setActiveButton(document.getElementById("areaButton"));
                            break;
                        case null:
                            if (activeWidget) {
                                view.ui.remove(activeWidget);
                                activeWidget.destroy();
                                activeWidget = null;
                            }
                            break;
                    }
                }
    
                function setActiveButton(selectedButton) {
                    // focus the view to activate keyboard shortcuts for sketching
                    view.focus();
                    let elements = document.getElementsByClassName("active");
                    for (let i = 0; i < elements.length; i++) {
                        elements[i].classList.remove("active");
                    }
                    if (selectedButton) {
                        selectedButton.classList.add("active");
                    }
                }
    
    
    
            });
        </script>
    </head>
    
    <body>
        <div id="viewDiv"></div>
        <div id="topbar">
            <button class="action-button esri-icon-measure-line" id="distanceButton" type="button"
                title="Measure distance between two or more points"></button>
            <button class="action-button esri-icon-measure-area" id="areaButton" type="button"
                title="Measure area"></button>
        </div>
    </body>
    
    </html>