Measurement Widget - Adding multiple location points to map

1147
4
Jump to solution
07-10-2019 11:52 AM
BartPittari
New Contributor III

Is there a way to extend the Measurement Widget's Location function to allow for multiple pin locations on a map, and for those pins to be removed individually by the user?  I've got a pin function that I'm using for another part of some code that I'm developing against and, before I try to try and leverage it similarly on this part, I wanted to ask. 

I'm using v 3.16 & Dojo for this. 

B

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Bart,

   Here is a sample. Don't forget to mark this question as answered by clicking on the "Mark Correct" link on the reply that answered your question.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--The viewport meta tag is used to improve the presentation and behavior of the samples
    on iOS devices-->
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Measure Tool</title>
  <link rel="stylesheet" href="http://js.arcgis.com/3.21/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.21/esri/css/esri.css">
  <style>
    html,
    body {
      height: 100%;
      width: 100%;
      margin: 0;
    }

    body {
      background-color: #FFF;
      overflow: hidden;
      font-family: "Trebuchet MS";
    }

    #map {
      border: solid 2px #808775;
      -moz-border-radius: 4px;
      -webkit-border-radius: 4px;
      border-radius: 4px;
      margin: 5px;
      padding: 0px;
    }

    #titlePane {
      width: 240px;
    }

    .claro .dijitTitlePaneTitle {
      background: #fff;
      font-weight: 600;
      border: none;
      border-bottom: solid 1px #29201A;
      border-top: solid 1px #29201A;
    }

    .claro .dijitTitlePaneTitleHover {
      background: #eee;
    }

    .claro .dijitTitlePaneTitleActive {
      background: #808775;
    }

    .claro .dijitTitlePaneContentOuter {
      border-right: none;
      border-bottom: none;
      border-left: none;
    }
  </style>
  <script src="http://js.arcgis.com/3.21/"></script>
  <script>
    var map, deleteMGra;
    require([
        "dojo/dom",
        "esri/Color",
        "dojo/keys",
        "dojo/parser",
        "dojo/query",
        "dojo/on",
        "dojo/dom-construct",
        "dojo/_base/array",
        "dojo/dom-style",

        "esri/config",
        "esri/sniff",
        "esri/map",
        "esri/SnappingManager",
        "esri/dijit/Measurement",
        "esri/layers/FeatureLayer",
        "esri/layers/GraphicsLayer",
        "esri/graphic",
        "esri/renderers/SimpleRenderer",
        "esri/tasks/GeometryService",
        "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",
        "esri/symbols/PictureMarkerSymbol",

        "esri/dijit/Scalebar",
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
        "dijit/TitlePane",
        "dijit/form/CheckBox",
        "dojo/domReady!"
      ], function (
      dom, Color, keys, parser, query, on, domConstruct, array, domStyle,
      esriConfig, has, Map, SnappingManager, Measurement, FeatureLayer, GraphicsLayer, Graphic,
      SimpleRenderer, GeometryService, SimpleLineSymbol, SimpleFillSymbol, PictureMarkerSymbol
    ) {
      parser.parse();
      //This sample may require a proxy page to handle communications with the ArcGIS Server services. You will need to
      //replace the url below with the location of a proxy on your machine. See the 'Using the proxy page' help topic
      //for details on setting up a proxy page.
      esriConfig.defaults.io.proxyUrl = "/proxy/";
      esriConfig.defaults.io.alwaysUseProxy = false;

      //This service is for development and testing purposes only. We recommend that you create your own geometry service for use within your applications
      esriConfig.defaults.geometryService = new GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

      map = new Map("map", {
        basemap: "satellite",
        center: [-85.743, 38.256],
        zoom: 17
      });

      var sfs = new SimpleFillSymbol(
        "solid",
        new SimpleLineSymbol("solid", new Color([195, 176, 23]), 2),
        null
      );

      var parcelsLayer = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Louisville/LOJIC_LandRecords_Louisville/MapServer/0", {
        mode: FeatureLayer.MODE_ONDEMAND,
        outFields: ["*"]
      });
      parcelsLayer.setRenderer(new SimpleRenderer(sfs));
      map.addLayers([parcelsLayer]);

      //dojo.keys.copyKey maps to CTRL on windows and Cmd on Mac., but has wrong code for Chrome on Mac
      var snapManager = map.enableSnapping({
        snapKey: has("mac") ? keys.META : keys.CTRL
      });
      var layerInfos = [{
        layer: parcelsLayer
        }];
      snapManager.setLayerInfos(layerInfos);

      var measureGL = new GraphicsLayer();
      var pms = new PictureMarkerSymbol('http://js.arcgis.com/3.21/esri/dijit/images/esriGreenPin16x26.png', 16, 26);
      pms.setOffset(0, 12);
      map.addLayers([measureGL]);

      var measurement = new Measurement({
        map: map,
      }, dom.byId("measurementDiv"));
      measurement.startup();

      measurement.on("tool-change", function (evt) {
        if (evt.toolName !== "location") {
          //If a tool other than the location tool or the location tool has been toggled off
          //Clear the graphics layer
          measureGL.clear();
          //Remove all the rows of locations added by the code
          var rows = query(".myMeasurementTableRow");
          array.forEach(rows, function (row) {
            domConstruct.destroy(row);
          });
          //Hide the Graphics Layer
          measureGL.hide();
        } else {
          //Hide the Graphics Layer
          measureGL.show();
          //show the standard location measure row that was hidden
          var mRows = query(".esriMeasurementTableRow");
          domStyle.set(mRows[1], "display", "");
        }
      });

      measurement.on("measure", function (evt) {
        switch (evt.toolName) {
        case "location":
          break;
        default:
          var resultDiv = query(".dijitContentPane .esriMeasurementResultValue")[0];
          console.info(measurement);
          var result = domConstruct.toDom("<div class='result'>" + evt.values[0] + "<div>");
          domConstruct.place(resultDiv, result);
          break;
        }
      });

      deleteMGra = function (){
        var rowId = this.event.target.id;
        domConstruct.destroy(this.event.target.id);
        //loop trough the graphics and delete this graphic by ID
        measureGL.graphics.some(function(g){
          if(g.attributes.Id === rowId){
            measureGL.remove(g);
            if(measureGL.graphics.length == 0){
              measurement.clearResult();
            }
            return true;
          }
        })
      }

      measurement.on("measure-end", function (evt) {
        switch (evt.toolName) {
        case "location":
          //console.log("Lat: " + evt.values[0] + " Lng: " + evt.values[1]);
          var tbl = query(".esriMeasurementResultTable tbody")[0];
          var eRows = query(".esriMeasurementTableRow");
          var mRows = query(".myMeasurementTableRow");
          var rowId = "mrowid" + (mRows.length + 1 ).toString();
          var row = domConstruct.toDom("<tr class='myMeasurementTableRow' id='" + rowId + "'>" +
            "<td><img src='http://js.arcgis.com/3.14/esri/dijit/images/esriGreenPin16x26.png' style='vertical-align:middle'></td>" +
            "<td class='esriMeasurementTableCell'>" + evt.values[0] + "</td><td class='esriMeasurementTableCell'>" + evt.values[1] + 
            "</td><td><span style='cursor:pointer;color:red;font-weight:bold;padding:0 2px;' id='" + rowId + "'" +
            " onClick='deleteMGra()'>X</span></td></tr>");
          //Hide the standard measure loaction row so that there is not two identical measures
          domStyle.set(eRows[1], "display", "none");
          domConstruct.place(row, tbl);
          //Add the measure to the Graphics Layer
          measureGL.add(new Graphic(evt.geometry, pms, {
            "Lat": evt.values[0],
            "Lon": evt.values[1],
            "Id": rowId
          }));
          measurement._measureGraphics[0]._graphicsLayer.clear();
          break;
        default:
          var resultDiv = query(".esriMeasurementResultValue")[0];
          var result = domConstruct.toDom("<div class='result'>" + evt.values[0] + "<div>");
          domConstruct.place(resultDiv, result);
          break;
        }
      });
    });
  </script>
</head>

<body class="claro">
  <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false" style="width:100%; height:100%;">
    <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
      <div style="position:absolute; right:20px; top:10px; z-Index:999;">
        <div id="titlePane" data-dojo-type="dijit/TitlePane" data-dojo-props="title:'Measurement', closable:'false', open:'false'">
          <div id="measurementDiv"></div>
          <span style="font-size:smaller;padding:5px 5px;">Press <b>CTRL</b> to enable snapping.</span>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

View solution in original post

4 Replies
RobertScheitlin__GISP
MVP Emeritus

Bart,

   Something like this? You can place multiple points on the map and right click a point to delete it.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Measure Tool</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.29/esri/themes/calcite/dijit/calcite.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.29/esri/themes/calcite/esri/esri.css">
    <style>
      html,body {
        height:100%;
        width:100%;
        margin:0;
      }
      body {
        background-color:#FFF;
        overflow:hidden;
        font-family:"Trebuchet MS";
      }
      #map {
        border:solid 2px #808775;
        -moz-border-radius:4px;
        -webkit-border-radius:4px;
        border-radius:4px;
        margin:5px;
        padding:0px;
      }
      #titlePane{
        width:280px;
      }
      </style>
      <script src="https://js.arcgis.com/3.29/"></script>
    <script>
    var map;
    require([
        "dojo/dom",
        "esri/Color",
        "dojo/keys",
        "dojo/parser",

        "esri/config",
        "esri/sniff",
        "esri/map",
        "esri/SnappingManager",
        "esri/dijit/Measurement",
        "esri/layers/FeatureLayer",
        "esri/renderers/SimpleRenderer",
        "esri/tasks/GeometryService",
        "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",
        "esri/layers/GraphicsLayer",
        "esri/graphic",
        "dijit/Menu", "dijit/MenuItem", "dijit/MenuSeparator",

        "esri/dijit/Scalebar",
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
        "dijit/TitlePane",
        "dijit/form/CheckBox",
        "dojo/domReady!"
      ], function(
        dom, Color, keys, parser,
        esriConfig, has, Map, SnappingManager, Measurement, FeatureLayer, SimpleRenderer, GeometryService, SimpleLineSymbol, SimpleFillSymbol, GraphicsLayer, Graphic,
          Menu, MenuItem, MenuSeparator
      ) {
        parser.parse();
        //This sample may require a proxy page to handle communications with the ArcGIS Server services. You will need to
        //replace the url below with the location of a proxy on your machine. See the 'Using the proxy page' help topic
        //for details on setting up a proxy page.
        esriConfig.defaults.io.proxyUrl = "/proxy/";
        esriConfig.defaults.io.alwaysUseProxy = false;

        //This service is for development and testing purposes only. We recommend that you create your own geometry service for use within your applications
        esriConfig.defaults.geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

        map = new Map("map", {
          basemap: "satellite",
          center: [-85.743, 38.256],
          zoom: 17
        });
        var mGL = new GraphicsLayer();
        map.on("load", createGraphicsMenu);
        
        function createGraphicsMenu() {
          map.addLayer(mGL);
          
          // Creates right-click context menu for GRAPHICS
          ctxMenuForGraphics = new Menu({});
          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Delete",
            onClick: function() {
              mGL.remove(selected);
            }
          }));

          ctxMenuForGraphics.startup();

          mGL.on("mouse-over", function(evt) {
            // We'll use this "selected" graphic to enable editing tools
            // on this graphic when the user click on one of the tools
            // listed in the menu.
            selected = evt.graphic;

            // Let's bind to the graphic underneath the mouse cursor           
            ctxMenuForGraphics.bindDomNode(evt.graphic.getDojoShape().getNode());
          });

          mGL.on("mouse-out", function(evt) {
            ctxMenuForGraphics.unBindDomNode(evt.graphic.getDojoShape().getNode());
          });
        }

        var sfs = new SimpleFillSymbol(
          "solid",
          new SimpleLineSymbol("solid", new Color([195, 176, 23]), 2),
          null
        );

        var parcelsLayer = new FeatureLayer("https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Louisville/LOJIC_LandRecords_Louisville/MapServer/0", {
          mode: FeatureLayer.MODE_ONDEMAND,
          outFields: ["*"]
        });
        parcelsLayer.setRenderer(new SimpleRenderer(sfs));
        map.addLayers([parcelsLayer]);

        //dojo.keys.copyKey maps to CTRL on windows and Cmd on Mac., but has wrong code for Chrome on Mac
        var snapManager = map.enableSnapping({
          snapKey: has("mac") ? keys.META : keys.CTRL
        });
        var layerInfos = [{
          layer: parcelsLayer
        }];
        snapManager.setLayerInfos(layerInfos);

        var measurement = new Measurement({
          map: map
        }, dom.byId("measurementDiv"));
        measurement.startup();
        measurement.on('measure-end', function(evt){
          var geom = evt.geometry;
          console.info(measurement);
          var gra = new Graphic(geom, measurement._pointSymbol)
          measurement.clearResult();
          mGL.add(gra);
        });
        
      });
    </script>
  </head>

  <body class="calcite">
    <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false"
    style="width:100%; height:100%;">
      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
        <div style="position:absolute; right:20px; top:10px; z-Index:999;">
          <div id="titlePane" data-dojo-type="dijit/TitlePane" data-dojo-props="title:'Measurement', closable:false">
            <div id="measurementDiv"></div>
            <span style="font-size:smaller;padding:5px 5px;">Press <b>CTRL</b> to enable snapping.</span>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
0 Kudos
BartPittari
New Contributor III

Robert,

That's along the lines of what I was trying to do.  I'm needing to add the points to a list which I was going to put below where the green pin marker was located.  From there, they would have the option to remove individual ones or clear the list. 

Bart

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Yet totally possible.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Bart,

   Here is a sample. Don't forget to mark this question as answered by clicking on the "Mark Correct" link on the reply that answered your question.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--The viewport meta tag is used to improve the presentation and behavior of the samples
    on iOS devices-->
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Measure Tool</title>
  <link rel="stylesheet" href="http://js.arcgis.com/3.21/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.21/esri/css/esri.css">
  <style>
    html,
    body {
      height: 100%;
      width: 100%;
      margin: 0;
    }

    body {
      background-color: #FFF;
      overflow: hidden;
      font-family: "Trebuchet MS";
    }

    #map {
      border: solid 2px #808775;
      -moz-border-radius: 4px;
      -webkit-border-radius: 4px;
      border-radius: 4px;
      margin: 5px;
      padding: 0px;
    }

    #titlePane {
      width: 240px;
    }

    .claro .dijitTitlePaneTitle {
      background: #fff;
      font-weight: 600;
      border: none;
      border-bottom: solid 1px #29201A;
      border-top: solid 1px #29201A;
    }

    .claro .dijitTitlePaneTitleHover {
      background: #eee;
    }

    .claro .dijitTitlePaneTitleActive {
      background: #808775;
    }

    .claro .dijitTitlePaneContentOuter {
      border-right: none;
      border-bottom: none;
      border-left: none;
    }
  </style>
  <script src="http://js.arcgis.com/3.21/"></script>
  <script>
    var map, deleteMGra;
    require([
        "dojo/dom",
        "esri/Color",
        "dojo/keys",
        "dojo/parser",
        "dojo/query",
        "dojo/on",
        "dojo/dom-construct",
        "dojo/_base/array",
        "dojo/dom-style",

        "esri/config",
        "esri/sniff",
        "esri/map",
        "esri/SnappingManager",
        "esri/dijit/Measurement",
        "esri/layers/FeatureLayer",
        "esri/layers/GraphicsLayer",
        "esri/graphic",
        "esri/renderers/SimpleRenderer",
        "esri/tasks/GeometryService",
        "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",
        "esri/symbols/PictureMarkerSymbol",

        "esri/dijit/Scalebar",
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
        "dijit/TitlePane",
        "dijit/form/CheckBox",
        "dojo/domReady!"
      ], function (
      dom, Color, keys, parser, query, on, domConstruct, array, domStyle,
      esriConfig, has, Map, SnappingManager, Measurement, FeatureLayer, GraphicsLayer, Graphic,
      SimpleRenderer, GeometryService, SimpleLineSymbol, SimpleFillSymbol, PictureMarkerSymbol
    ) {
      parser.parse();
      //This sample may require a proxy page to handle communications with the ArcGIS Server services. You will need to
      //replace the url below with the location of a proxy on your machine. See the 'Using the proxy page' help topic
      //for details on setting up a proxy page.
      esriConfig.defaults.io.proxyUrl = "/proxy/";
      esriConfig.defaults.io.alwaysUseProxy = false;

      //This service is for development and testing purposes only. We recommend that you create your own geometry service for use within your applications
      esriConfig.defaults.geometryService = new GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

      map = new Map("map", {
        basemap: "satellite",
        center: [-85.743, 38.256],
        zoom: 17
      });

      var sfs = new SimpleFillSymbol(
        "solid",
        new SimpleLineSymbol("solid", new Color([195, 176, 23]), 2),
        null
      );

      var parcelsLayer = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Louisville/LOJIC_LandRecords_Louisville/MapServer/0", {
        mode: FeatureLayer.MODE_ONDEMAND,
        outFields: ["*"]
      });
      parcelsLayer.setRenderer(new SimpleRenderer(sfs));
      map.addLayers([parcelsLayer]);

      //dojo.keys.copyKey maps to CTRL on windows and Cmd on Mac., but has wrong code for Chrome on Mac
      var snapManager = map.enableSnapping({
        snapKey: has("mac") ? keys.META : keys.CTRL
      });
      var layerInfos = [{
        layer: parcelsLayer
        }];
      snapManager.setLayerInfos(layerInfos);

      var measureGL = new GraphicsLayer();
      var pms = new PictureMarkerSymbol('http://js.arcgis.com/3.21/esri/dijit/images/esriGreenPin16x26.png', 16, 26);
      pms.setOffset(0, 12);
      map.addLayers([measureGL]);

      var measurement = new Measurement({
        map: map,
      }, dom.byId("measurementDiv"));
      measurement.startup();

      measurement.on("tool-change", function (evt) {
        if (evt.toolName !== "location") {
          //If a tool other than the location tool or the location tool has been toggled off
          //Clear the graphics layer
          measureGL.clear();
          //Remove all the rows of locations added by the code
          var rows = query(".myMeasurementTableRow");
          array.forEach(rows, function (row) {
            domConstruct.destroy(row);
          });
          //Hide the Graphics Layer
          measureGL.hide();
        } else {
          //Hide the Graphics Layer
          measureGL.show();
          //show the standard location measure row that was hidden
          var mRows = query(".esriMeasurementTableRow");
          domStyle.set(mRows[1], "display", "");
        }
      });

      measurement.on("measure", function (evt) {
        switch (evt.toolName) {
        case "location":
          break;
        default:
          var resultDiv = query(".dijitContentPane .esriMeasurementResultValue")[0];
          console.info(measurement);
          var result = domConstruct.toDom("<div class='result'>" + evt.values[0] + "<div>");
          domConstruct.place(resultDiv, result);
          break;
        }
      });

      deleteMGra = function (){
        var rowId = this.event.target.id;
        domConstruct.destroy(this.event.target.id);
        //loop trough the graphics and delete this graphic by ID
        measureGL.graphics.some(function(g){
          if(g.attributes.Id === rowId){
            measureGL.remove(g);
            if(measureGL.graphics.length == 0){
              measurement.clearResult();
            }
            return true;
          }
        })
      }

      measurement.on("measure-end", function (evt) {
        switch (evt.toolName) {
        case "location":
          //console.log("Lat: " + evt.values[0] + " Lng: " + evt.values[1]);
          var tbl = query(".esriMeasurementResultTable tbody")[0];
          var eRows = query(".esriMeasurementTableRow");
          var mRows = query(".myMeasurementTableRow");
          var rowId = "mrowid" + (mRows.length + 1 ).toString();
          var row = domConstruct.toDom("<tr class='myMeasurementTableRow' id='" + rowId + "'>" +
            "<td><img src='http://js.arcgis.com/3.14/esri/dijit/images/esriGreenPin16x26.png' style='vertical-align:middle'></td>" +
            "<td class='esriMeasurementTableCell'>" + evt.values[0] + "</td><td class='esriMeasurementTableCell'>" + evt.values[1] + 
            "</td><td><span style='cursor:pointer;color:red;font-weight:bold;padding:0 2px;' id='" + rowId + "'" +
            " onClick='deleteMGra()'>X</span></td></tr>");
          //Hide the standard measure loaction row so that there is not two identical measures
          domStyle.set(eRows[1], "display", "none");
          domConstruct.place(row, tbl);
          //Add the measure to the Graphics Layer
          measureGL.add(new Graphic(evt.geometry, pms, {
            "Lat": evt.values[0],
            "Lon": evt.values[1],
            "Id": rowId
          }));
          measurement._measureGraphics[0]._graphicsLayer.clear();
          break;
        default:
          var resultDiv = query(".esriMeasurementResultValue")[0];
          var result = domConstruct.toDom("<div class='result'>" + evt.values[0] + "<div>");
          domConstruct.place(resultDiv, result);
          break;
        }
      });
    });
  </script>
</head>

<body class="claro">
  <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false" style="width:100%; height:100%;">
    <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
      <div style="position:absolute; right:20px; top:10px; z-Index:999;">
        <div id="titlePane" data-dojo-type="dijit/TitlePane" data-dojo-props="title:'Measurement', closable:'false', open:'false'">
          <div id="measurementDiv"></div>
          <span style="font-size:smaller;padding:5px 5px;">Press <b>CTRL</b> to enable snapping.</span>
        </div>
      </div>
    </div>
  </div>
</body>

</html>