SnapManager fails to complete snap in Javascript

4035
5
Jump to solution
12-04-2015 02:30 PM
TylerJones3
New Contributor III

Using the Web Application Builder, I am trying to make a Measurement widget that will snap to one particular (line) feature layer. The snapping at first appears to be working on the map: Hovering the mouse near a feature will create the default blue + symbol on the feature. However, no actual snap occurs when the mouse is clicked. The same happens when trying to complete the measurement. The start and end points don't actually snap at all, they are set where the mouse pointer is, not where the blue + is.

I found that if I do not specify layerInfos in the code below (line 25), the snapping works correctly. The problem is that the snapping manager will not use my line feature layer and instead defaults to a different layer in the map. What is wrong in the code below that is causing the actual snap part of the process to fail?

Lines 01 to 14 is a for loop that is finding my line layer (Distribution). Lines 17 to 25 are getting the snapManager set up with the right properties and layer to snap to.

var url = "";
for(var j = 0; j < this.map.layerIds.length; j++) {
    var layer = this.map.getLayer(this.map.layerIds);
    var items = layer.layerInfos;
        for (h = 0; h < items.length; h++) {
          
          if (items.name === "Distribution"){
              if (url === ""){
                    url = layer.url + "/" + items.id;
              }
             break;
            }
        }
}
   
  
var snaplayer =  new FeatureLayer(url);
var snapManager = this.map.enableSnapping({
    tolerance: 30,
    alwaysSnap: true
});
var layerInfos = [{
    layer: snaplayer
}];
snapManager.setLayerInfos(layerInfos);
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Tyler,

    Right now you are creating a new FeatureLayer and not adding it to the map so this is problematic. I found similar results as yours when in testing I did not add the new FeatureLayer to the map and ensure that it was loaded.

View solution in original post

0 Kudos
5 Replies
RobertScheitlin__GISP
MVP Emeritus

Tyler,

    Right now you are creating a new FeatureLayer and not adding it to the map so this is problematic. I found similar results as yours when in testing I did not add the new FeatureLayer to the map and ensure that it was loaded.

0 Kudos
TylerJones3
New Contributor III

Okay, I understand. I went one step further and added the layer to the map and the snapping works at that point. What I am trying to do is take a sublayer--Distribution in this case--from an operational layer that is already in the map and set the snapping to just work on that one sublayer. So far I have had no success--hence the attempt to go get the Distribution layer and use it directly. Is it possible to set snapping to a sublayer like this without having to add it to the map as a feature layer?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tyler,

   No a ArcGISDynamicMapService layer is just a image returned from ArcGIS Serevr and the client does not know about the sublayer geometry to be able to snap to it. When adding the sub layer as a FeatureLayer ArcGIS Server return the actual geometry that is need to allow for snapping. You can try and set the FeatureLayers opacity or visibility if the fact that the FeatureLayer is drawn on the map is causing you frustration.

0 Kudos
TylerJones3
New Contributor III

Good to know. Thanks for the help.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tyler,

  Here is the JS API code I used in testing this:

<!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.15/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="https://js.arcgis.com/3.15/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="https://js.arcgis.com/3.15/"></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/layers/ArcGISDynamicMapServiceLayer",
        "esri/renderers/SimpleRenderer",
        "esri/tasks/GeometryService",
        "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",

        "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, ArcGISDynamicMapServiceLayer, SimpleRenderer, GeometryService,
      SimpleLineSymbol, SimpleFillSymbol
    ) {
      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 = "http://gislap183/Proxy/proxy.ashx";
      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: "topo",
        center: [-94.75290067627297, 39.034671990514816], // long, lat
        zoom: 12,
        sliderStyle: "small"
      });

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

      var oilAndGasLayer0 = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Petroleum/KGS_OilGasFields_Kansas/MapServ...", {
        mode: FeatureLayer.MODE_ONDEMAND,
        outFields: ["*"]
      });
      map.addLayers([oilAndGasLayer0]);


      var demographicsLayerURL = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer";
      var demographicsLayerOptions = {
        "id": "demographicsLayer",
        "opacity": 0.8,
        "showAttribution": false
      };
      var demographicsLayer = new ArcGISDynamicMapServiceLayer(demographicsLayerURL, demographicsLayerOptions);
      demographicsLayer.setVisibleLayers([1, 2]);
      map.addLayer(demographicsLayer);

      var oilAndGasLayer = new ArcGISDynamicMapServiceLayer(
        "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Petroleum/KGS_OilGasFields_Kansas/MapServ...", {
          "id": "oilAndGasLayer",
          "opacity": 0.75
        });
      map.addLayer(oilAndGasLayer);

      var snapManager = map.enableSnapping({
        tolerance: 30,
        alwaysSnap: true
      });
      var layerInfos = [{
        layer: oilAndGasLayer0
      }];
      snapManager.setLayerInfos(layerInfos);

      var measurement = new Measurement({
        map: map
      }, dom.byId("measurementDiv"));
      measurement.startup();
    });
  </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>