Multiple ArcGISDynamicMapServiceLayer (rasters) and Identify Task

1071
4
Jump to solution
08-02-2019 06:33 AM
FengYu
by
New Contributor III

I am trying to incorporate the code from this thread into my work but it seems something is wrong.

multiple ArcGISDynamicMapServiceLayer IdentifyTask 

I would appreciate your help. Thanks.

<!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>soil map</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.29/dijit/themes/claro/claro.css">

    <link rel="stylesheet" href="https://js.arcgis.com/3.29/esri/css/esri.css">

    <style>
      html, body, .container, #map {
        height:100%;
        width:100%;
        margin:0;
        padding:0;
        margin:0;
        font-family: "Open Sans";
      }
#map {
    padding:0;
} 
#layerListPane{
    width:25%;
} 
.esriLayer{
  background-color: #fff;
} 
.esriLayerList .esriList{
    border-top:none;
} 
.esriLayerList .esriTitle {
  background-color: #fff;
  border-bottom:none;
} 
.esriLayerList .esriList ul{
  background-color: #fff;
}
    #search {
    display: block;
    position: absolute;
    z-index: 3;
        top: 20px;
        left: 75px;
      }
    #HomeButton {
      position: absolute;
      top: 100px;
      left: 15px;
      z-index: 50;
    }
    </style>
    //<script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="http://js.arcgis.com/3.29/"></script>
    <script>
      require([
        "dojo/parser",
        "esri/dijit/Popup",
        "esri/symbols/SimpleFillSymbol",
        "esri/symbols/SimpleLineSymbol",
        "esri/Color",
        "dojo/dom-construct",
        "esri/map",
    "esri/dijit/HomeButton",
        "esri/layers/ArcGISDynamicMapServiceLayer",
        "esri/dijit/LayerList",
        "esri/dijit/Search",
    "esri/dijit/Legend",
    "esri/dijit/Scalebar",
        "esri/tasks/IdentifyTask",
        "esri/tasks/IdentifyParameters",
        "dojo/_base/array",
        "esri/InfoTemplate",
        "dojo/dom",
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
        "dojo/promise/all",
        "dojo/domReady!"
      ], function (
        parser, Popup, SimpleFillSymbol, SimpleLineSymbol, Color, domConstruct, 
        Map, HomeButton, ArcGISDynamicMapServiceLayer, LayerList, Search, Legend, Scalebar,
         IdentifyTask, IdentifyParameters,  arrayUtils, InfoTemplate, All,
          dom
      ) {
        parser.parse();
        var map, identifyTask, identifyParams;

        var popup = new Popup({
          fillSymbol: new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
              new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.25]))
        }, domConstruct.create("div"));


        map = new Map("map", {
          basemap: "topo",
          center: [-90.125, 40],
          zoom: 8,
          infoWindow: popup
        });

        dojo.connect(map, "onLoad", mapReady);  

        var rasterURL1 = "https://mapsweb.lib.purdue.edu/arcgis/rest/services/Ag/Subirrigation_suitability/MapServer";

        var operationalLayer1 = new ArcGISDynamicMapServiceLayer(rasterURL1,{ opacity: .90 });


        var rasterURL2 = "https://mapsweb.lib.purdue.edu/arcgis/rest/services/Ag/Drainage_class/MapServer";

        var operationalLayer2 = new ArcGISDynamicMapServiceLayer(rasterURL5,{ opacity: .90 });
        map.addLayers([operationalLayer1,operationalLayer2]);


        var layerList = new LayerList({
        map: map,
       layers: [
    {
    layer: operationalLayer1,
    id: "Subirrigation_suitability"
    },
    {
    layer: operationalLayer2,
    id: "Drainage_class"
    }
                ],
       showLegend: true,
       showSubLayers: false,
       showOpacitySlider: false
       },"layerList");
       layerList.startup();

        var search = new Search({
            map: map,
             }, dom.byId("search"));

        search.startup();

       var home = new HomeButton({
        map: map
       }, "HomeButton");
       home.startup();

        var scalebar = new Scalebar({
          map: map,
          scalebarUnit: "dual"
        });
    scalebar.startup();

            function mapReady(map) {  
                dojo.connect(map, "onClick", runIdentifies);  
            }  

            function runIdentifies(evt) {  
                identifyResults = [];  
                idPoint = evt.mapPoint;  
                var layers = dojo.map(map.layerIds, function (layerId) {  
                    return map.getLayer(layerId);  
                });  
                layers = dojo.filter(layers, function (layer) {  
                    if (layer.visibleLayers[0] !== -1) {  
                        return layer.getImageUrl && layer.visible  
                    }  
                }); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers  
                var tasks = dojo.map(layers, function (layer) {  
                    return new esri.tasks.IdentifyTask(layer.url);  
                }); //map each visible dynamic layer to a new identify task, using the layer url  
                var defTasks = dojo.map(tasks, function (task) {  
                    return new dojo.Deferred();  
                }); //map each identify task to a new dojo.Deferred  
                var params = createIdentifyParams(layers, evt);  
  
                var promises = [];  
  
                for (i = 0; i < tasks.length; i++) {  
                    promises.push(tasks[i].execute(params[i])); //Execute each task  
                } 
                //document.write(r); 
  
                var allPromises = new All(promises);  
                allPromises.then(function (r) { executeIdentifyTask(r, tasks); });  
            }

      
            function createIdentifyParams(layers, evt) {  
                var identifyParamsList = [];  
                identifyParamsList.length = 0;  
                dojo.forEach(layers, function (layer) {  
                    var idParams = new esri.tasks.IdentifyParameters();  
                    idParams.width = map.width;  
                    idParams.height = map.height;  
                    idParams.geometry = evt.mapPoint;  
                    idParams.mapExtent = map.extent;  
                    idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;  
                    var visLayers = layer.visibleLayers;  
                    if (visLayers !== -1) {  
                        var subLayers = [];  
                        for (var i = 0; i < layer.layerInfos.length; i++) {  
                            if (layer.layerInfos[i].subLayerIds == null)  
                                subLayers.push(layer.layerInfos[i].id);  
                        }  
                        idParams.layerIds = subLayers;  
                    } else {  
                        idParams.layerIds = [];  
                    }  
                    idParams.tolerance = 3;  
                    idParams.returnGeometry = true;  
                    identifyParamsList.push(idParams);  
                });  
                return identifyParamsList;  
            }  
 

function executeIdentifyTask(r, tasks) {  
                var results = [];  
                var taskUrls = [];  
                r = dojo.filter(r, function (result) {  
                    return r[0];  
                });  
                for (i = 0; i < r.length; i++) {  
                    results = results.concat(r[i]);  
                    for (j = 0; j < r[i].length; j++) {  
                        taskUrls = taskUrls.concat(tasks[i].url);  
                    }  
                } 
                window.alert(taskUrls); 
                results = dojo.map(results, function (result, index) {  
                    var feature = result.feature;  
                    var layerName = result.layerName;  
                    var serviceUrl = taskUrls[index];  
                    feature.attributes.layerName = result.layerName;  
  
                    var template = new InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "Subirrigation suitability for this pixel is (scaled at 0-1): " + parseFloat(feature.attributes['Pixel Value']).toFixed(2));  
                    feature.setInfoTemplate(template);  
  
                    var resultGeometry = feature.geometry;  
                    var resultType = resultGeometry.type;  
                    return feature;  
                });  
  
                if (results.length === 0) {  
                    map.infoWindow.clearFeatures();  
                } else {  
                    map.infoWindow.setFeatures(results);  
                }  
                map.infoWindow.show(idPoint);  
                return results;  
            }  

      });      
      
    </script>
  </head>
  
  <body class="claro">

<div class="container" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline', gutters:false" style="width:100%; height:100%;">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
    <div id="layerList"></div>

</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
      <div id="search"></div>
      <div id="HomeButton"></div>
</div>
</div>

  </body>


</html>
0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

There were two errors. First the order of the function arguments don't agree with the modules. This is what it should look like ("dojo/promise/all" moved to line 19)

    require([
      "dojo/parser",
      "esri/dijit/Popup",
      "esri/symbols/SimpleFillSymbol",
      "esri/symbols/SimpleLineSymbol",
      "esri/Color",
      "dojo/dom-construct",
      "esri/map",
      "esri/dijit/HomeButton",
      "esri/layers/ArcGISDynamicMapServiceLayer",
      "esri/dijit/LayerList",
      "esri/dijit/Search",
      "esri/dijit/Legend",
      "esri/dijit/Scalebar",
      "esri/tasks/IdentifyTask",
      "esri/tasks/IdentifyParameters",
      "dojo/_base/array",
      "esri/InfoTemplate",
      "dojo/promise/all",
      "dojo/dom",
      "dijit/layout/BorderContainer",
      "dijit/layout/ContentPane",
      "dojo/domReady!"
    ], function (
      parser, Popup, SimpleFillSymbol, SimpleLineSymbol, Color, domConstruct,
      Map, HomeButton, ArcGISDynamicMapServiceLayer, LayerList, Search, Legend, Scalebar,
      IdentifyTask, IdentifyParameters, arrayUtils, InfoTemplate, All,
      dom
    ) {‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Second, line 114 has a typo. You should be using "rasterURL2"

var operationalLayer2 = new ArcGISDynamicMapServiceLayer(rasterURL2, { opacity: .90 });

View solution in original post

4 Replies
KenBuja
MVP Esteemed Contributor

There were two errors. First the order of the function arguments don't agree with the modules. This is what it should look like ("dojo/promise/all" moved to line 19)

    require([
      "dojo/parser",
      "esri/dijit/Popup",
      "esri/symbols/SimpleFillSymbol",
      "esri/symbols/SimpleLineSymbol",
      "esri/Color",
      "dojo/dom-construct",
      "esri/map",
      "esri/dijit/HomeButton",
      "esri/layers/ArcGISDynamicMapServiceLayer",
      "esri/dijit/LayerList",
      "esri/dijit/Search",
      "esri/dijit/Legend",
      "esri/dijit/Scalebar",
      "esri/tasks/IdentifyTask",
      "esri/tasks/IdentifyParameters",
      "dojo/_base/array",
      "esri/InfoTemplate",
      "dojo/promise/all",
      "dojo/dom",
      "dijit/layout/BorderContainer",
      "dijit/layout/ContentPane",
      "dojo/domReady!"
    ], function (
      parser, Popup, SimpleFillSymbol, SimpleLineSymbol, Color, domConstruct,
      Map, HomeButton, ArcGISDynamicMapServiceLayer, LayerList, Search, Legend, Scalebar,
      IdentifyTask, IdentifyParameters, arrayUtils, InfoTemplate, All,
      dom
    ) {‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Second, line 114 has a typo. You should be using "rasterURL2"

var operationalLayer2 = new ArcGISDynamicMapServiceLayer(rasterURL2, { opacity: .90 });
FengYu
by
New Contributor III

Thanks Ken. I have a few more questions:

(1) How to change the popup text based on different layers?

(2) Is it possible to access the attribute table (The rasterURL2 has a attribute table with a text field and I would like to show the text instead of the value field)? 

(3) Can I show pixel values for two layers together in the identifytask popup box (even if I have only one layer toggled)? One layer is visible and the other layer is hidden. 

0 Kudos
KenBuja
MVP Esteemed Contributor

Since your initial question appeared to be answered, please remember to click the "Mark Correct" button.

1. You can use different popup templates depending on conditions you set. See this sample as an example: Format info window content | ArcGIS API for JavaScript 3.29 

2. You can access the text attributes of the raster like you've already done for the pixel value.

Something like this would answer these two questions

results = dojo.map(results, function (result, index) {
  var feature = result.feature;
  var layerName = result.layerName;
  var serviceUrl = taskUrls[index];
  feature.attributes.layerName = result.layerName;

  if (serviceUrl === rasterURL2) {
    var template = new InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "Subirrigation suitability for this pixel is (scaled at 0-1): " + parseFloat(feature.attributes['Pixel Value']).toFixed(2) + "<br/><br/>Drainage Class: " + result.feature.attributes.DrainageClass      );
  } else {
    var template = new InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "Subirrigation suitability for this pixel is (scaled at 0-1): " + parseFloat(feature.attributes['Pixel Value']).toFixed(2));
  }
  feature.setInfoTemplate(template);

  var resultGeometry = feature.geometry;
  var resultType = resultGeometry.type;
  return feature;
});
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

3. If I understand your question correctly, you would make this change to line 165 of your code. Originally, this line filters out a layer that is not visible.

return layer.getImageUrl// && layer.visible
FengYu
by
New Contributor III

Thanks Ken.

However, now the popup shows the values for all the layers. Is it possible to show only the toggled layers? (put the && layer.visible back?)  When the popup shows the value for a toggled layer, it also shows the value for a hidden layer (not included in the layerlist but added to the map and set as not visible). 

0 Kudos