通过 Javascript ArcGIS Api 从 TileLayer 绘制折线或多边形时如何获取特定区域中选定位置的值?

How to get value for selected place in particular area when draw polyline or polygon through Javascript ArcGIS Api from TileLayer?

实际上,我正在使用 ArcGIS API for JavaScript 4.7,并且我有一个自定义内部层。我想在绘制折线时获取特定区域的名称,列名称为 (PLC_NAME) 。如何实现? 假设我通过折线绘制一个区域。在这方面有地方。现在我需要获取这些地方的名称。

你可以在下面找到使用代码,我正在使用 TileLayer。

require([
"esri/views/MapView",
"esri/Map",
"esri/Basemap",
"esri/layers/TileLayer",
"esri/layers/MapImageLayer",
"esri/widgets/Sketch/SketchViewModel",
"esri/geometry/geometryEngine",
"esri/widgets/CoordinateConversion",
"esri/geometry/support/webMercatorUtils",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/config",
"esri/core/urlUtils",
"esri/widgets/Search",
"esri/tasks/Locator",
"esri/layers/FeatureLayer",
"esri/widgets/Expand",
"dojo/domReady!" 

], function (
MapView, Map, Basemap, TileLayer, MapImageLayer,
SketchViewModel,
 geometryEngine,
 CoordinateConversion, 
 webMercatorUtils,
 Graphic, GraphicsLayer, esriConfig, urlUtils,Search,Locator,FeatureLayer,Expand
) {

esriConfig.request.proxyUrl = "xxxxxxxxxxxxxxx";
    
urlUtils.addProxyRule({
    urlPrefix: "xxxxxxxxxxxxxxxxxxx",
    proxyUrl: "xxxxxxxxxxxxxxxxxx"

});

var tempGraphicsLayer = new GraphicsLayer();
var saveGraphicsLayer = new GraphicsLayer();    
var updateGraphic;
let highlight = null;
    'xxxxxxxxxxxxxxxxxxxxxxxxx';        
var myMap;

    var layer = new TileLayer({
        url: mapUrl            
    });
    var towerLayer = new MapImageLayer({
        url: 'xxxxxxxxxxxxxxxxxxxxxxx'
    });
    myMap = new Map({
        layers: [layer, tempGraphicsLayer, saveGraphicsLayer]
    });        
    myMap.add(towerLayer);
 

view = new MapView({
    center: [-55.1683665, 39.951817],
    container: "viewDiv",
    map: myMap,
    zoom: 14
});


var ccWidget = new CoordinateConversion({
    view: view
});


 // Adds the search widget below other elements in
// the top left corner of the view
view.ui.add(searchWidget, {
           position: "top-right",
           index: 1
            });

view.ui.add(ccWidget, "bottom-left");
view.ui.add("topbar", "top-right");
var pointSymbol = { // symbol used for points
    type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
    style: "square",
    color: "#8A2BE2",
    size: "16px",
    outline: { // autocasts as new SimpleLineSymbol()
        color: [255, 255, 255],
        width: 3 // points
    }
}
var polylineSymbol = { // symbol used for polylines
    type: "simple-line", // autocasts as new SimpleLineSymbol()
    color: "#8A2BE2",
    width: "4",
    style: "dash"
}
var polygonSymbol = { // symbol used for polygons
    type: "simple-fill", // autocasts as new SimpleFillSymbol()
    color: "rgba(138,43,226, 0.8)",
    style: "solid",
    outline: {
        color: "white",
        width: 1
    }
}

 var polygonBoundrySymbol = { // symbol used for polygons
    type: "simple-line", // autocasts as new SimpleFillSymbol()
    color: "red"
 }    
// ################## U R HERE ################## ################## U R HERE ################## 
################## U R HERE ################## 

let drawBoundry = function(){
    //let boundryJson = '&G_GEO_LIMITS.';
    let boundryJson = $v('P0_USER_LIMITS');
    if(boundryJson){
//            let boundry = Graphic.fromJSON(JSON.parse('&G_GEO_LIMITS.'));
        let boundry = Graphic.fromJSON(JSON.parse(boundryJson));            
        boundry.symbol = polygonBoundrySymbol;

        tempGraphicsLayer.add(boundry);
        return boundry;
    }         
}
/*
let boundry = drawBoundry();
    */


view.when(function () {
    $('.esri-view-root').on('click', '.esri-print__export-button', function(e){
        //console.log('event bubbling', e);
        //console.log('event bubbling this', this);
        e.preventDefault();
        saveExportedImg();
    });

    // create a new sketch view model
    var sketchViewModel = new SketchViewModel({
        view: view,
        layer: tempGraphicsLayer,
        pointSymbol: pointSymbol,
        polylineSymbol: polylineSymbol,
        polygonSymbol: polygonSymbol
    });
    

    //setUpClickHandler();
    // ************************************************************
    // Get the completed graphic from the event and add it to view.
    // This event fires when user presses
    // * "C" key to finish sketching point, polygon or polyline.
    // * Double-clicks to finish sketching polyline or polygon.
    // * Clicks to finish sketching a point geometry.
    // ***********************************************************
    sketchViewModel.on("draw-complete", addGraphic);
    sketchViewModel.on("update-complete", addGraphic);
    sketchViewModel.on("update-cancel", addGraphic);
    sketchViewModel.on("vertex-add", addGraphic);

    function addGraphic(evt) {
       // console.log ('graphic.geometry',evt.geometry)
        //let currentGraphic = popActiveGraphic(tempGraphicsLayer);
        let currentGraphic = saveGraphicsLayer.graphics.items.pop();
        
        var geometry = evt.geometry;
        var vertices = evt.vertices;
        var symbol;
        var attr = {
            Name: "Selected Area",
            X: $v('P24_X'),
            Y: $v('P24_Y')
        };
        // Choose a valid symbol based on return geometry
        switch (geometry.type) {
            case "point":
                symbol = pointSymbol;
                break;
            case "polyline":
                symbol = polylineSymbol;
                break;
            default:
                symbol = polygonSymbol;
                break;
        }
        // Create a new graphic; add it to the GraphicsLayer
       // console.log("b4 graphic");
        geometry =  webMercatorUtils.webMercatorToGeographic(geometry)
        /*if(boundry){
            var contains = geometryEngine.contains(boundry.geometry, geometry);
            var within = geometryEngine.within(geometry, boundry.geometry);                
        } else {*/
            var within = true;
        //}
                    
        if(within){
            
            let graphic = new Graphic({
                    geometry: geometry,
                    symbol: symbol,
                    //attributes: attr,
                    popupTemplate: {
                        title: "{Name}",
                        content: [{
                            type: "fields",
                            fieldInfos: [{
                                fieldName: "X"
                            }, {
                                fieldName: "Y"
                            }]
                        }]
                   }
            });                          
            tempGraphicsLayer.add(graphic);
            if(currentGraphic){
                //currentGraphic.geometry.rings.push(geometry.rings[0]);
                geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
                //currentGraphic.geometry.addRing(geometry.rings);
                //console.log('current active', geometry);
               // console.log('current graphic', currentGraphic.geometry);
                graphic = currentGraphic;                    
            }                 
            var saveObj = graphic.toJSON();                        
           // console.log('saveObj', saveObj);
            $x('P24_JSON').value = JSON.stringify(saveObj);
          
        } else {
            apex.message.alert('&G_MAP_BOUNDRY_MSG.');
        }
        updateGraphic = null;
    }
    
   
   function addMultiGraph(evt1) {
       
        //let currentGraphic = popActiveGraphic(tempGraphicsLayer);
        let currentGraphic = saveGraphicsLayer.graphics.items.pop();
        
        var geometry = evt1.geometry;
        var vertices = evt1.vertices;
        var symbol;
     
        // Choose a valid symbol based on return geometry
        switch (geometry.type) {
            case "point":
                symbol = pointSymbol;
                break;
            case "polyline":
                symbol = polylineSymbol;
                break;
            default:
                symbol = polygonSymbol;
                break;
        }
       //console.log("ring",geometry.rings )
            let graphic = new Graphic({
                    geometry: geometry,
                    symbol: symbol,
                    //attributes: attr,
                    popupTemplate: {
                        title: "{Name}",
                        content: [{
                            type: "fields",
                            fieldInfos: [{
                                fieldName: "X"
                            }, {
                                fieldName: "Y"
                            }]
                        }]
                   }
            });                       
            tempGraphicsLayer.add(graphic);
            if(currentGraphic){
                
                geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
                
            }              
            var saveObj1 = graphic.toJSON();                        
            //console.log('saveObj', graphic);
            $x('P24_JSON').value = JSON.stringify(saveObj1);
             
           
        
        updateGraphic = null;
    }

    window.loadGraphic = function(polygon){
        if(polygon===undefined || polygon === ''){
            console.error('no polygon');
        } else {
            
            
            var graphic = Graphic.fromJSON(JSON.parse(polygon));  
            if (graphic.geometry){
             
            
             
              addMultiGraph(graphic);
        
            //*********************************************************************
               view.center.longitude = graphic.geometry.centroid.longitude;
               view.center.latitude = graphic.geometry.centroid.latitude;
               view.center = [graphic.geometry.centroid.longitude, 
       graphic.geometry.centroid.latitude];
                view.zoom = 12;
            }
        }
        
    }
    

    
    // *************************************
    // activate the sketch to create a point
    // *************************************
    var drawPointButton = document.getElementById("pointButton");
    drawPointButton.onclick = function () {
        // set the sketch to create a point geometry
        sketchViewModel.create("point");
        setActiveButton(this);
    };
    // ****************************************
    // activate the sketch to create a polyline
    // ****************************************
    var drawLineButton = document.getElementById("polylineButton");
    drawLineButton.onclick = function () {
        // set the sketch to create a polyline geometry
        sketchViewModel.create("polyline");
        setActiveButton(this);
    };

    var drawPolygonButton = document.getElementById("polygonButton");
    drawPolygonButton.onclick = function () {
        // set the sketch to create a polygon geometry
        sketchViewModel.create("polygon");
        setActiveButton(this);
    };
    // ***************************************
    // activate the sketch to create a rectangle
    // ***************************************
    var drawRectangleButton = document.getElementById(
        "rectangleButton");
    drawRectangleButton.onclick = function () {
        // set the sketch to create a polygon geometry
        sketchViewModel.create("rectangle");
        setActiveButton(this);
    };

    document.getElementById("resetBtn").onclick = function () {
       sketchViewModel.reset();
      tempGraphicsLayer.removeAll();
      saveGraphicsLayer.removeAll();
      setActiveButton();
      drawBoundry();
    };

    function setActiveButton(selectedButton) {
        // focus the view to activate keyboard shortcuts for sketching
        view.focus();
        var elements = document.getElementsByClassName("active");
        for (var i = 0; i < elements.length; i++) {
            elements[i].classList.remove("active");
        }
        if (selectedButton) {
            selectedButton.classList.add("active");
        }
    }
    // ************************************************************************************
    // set up logic to handle geometry update and reflect the update on "tempGraphicsLayer"
    // ************************************************************************************
    function setUpClickHandler() {
        view.on("click", function (evt) {
            view.hitTest(evt).then(function (response) {
                var results = response.results;
                // Found a valid graphic                    
                if (results.length && results[results.length - 1]
                    .graphic) {
                    // Check if we're already editing a graphic
                    if (!updateGraphic) {
                        // Save a reference to the graphic we intend to update
                        updateGraphic = results[results.length - 1].graphic;
                        // Remove the graphic from the GraphicsLayer
                        // Sketch will handle displaying the graphic while being updated
                        tempGraphicsLayer.remove(updateGraphic);
                        sketchViewModel.update(updateGraphic.geometry);
                    }
                }
            });
        });
    } 
    

    function errorCallback(error) {
    console.log('error:', error);
  }
            // ************************************************************************************
    // returns graphic object if drawn on the map to contcat new graphics to it
    // ************************************************************************************
    function popActiveGraphic(graphicsLayer){            
        let length = graphicsLayer.graphics.length;
        let count = 0;
        if($v('P0_USER_LIMITS').length > 0){
            count++;
        }
        if(length > count){ //active drawing detected
            let result = graphicsLayer.graphics.items[length-1];
            graphicsLayer.remove(result);
            return result;
        }
    }
});
});

好的,您可以在客户端或服务器上解决查询。取决于您的任务,您可以选择哪些选项。

如果你打算使用空间查询,就像你提到的那样,你将把它应用到一个 FeatureLayer 上,你可以在客户端上解决它。这是一个很好的解决方案,因为您已经拥有这些功能,并且正在看到它们。在这种情况下,您有一个问题,

现在,如果您需要查询的内容可能不在您的范围内(您没有这些要素)或者您没有使用 FeatureLayer,您可能需要命令服务器执行此操作。但不要担心图书馆有几个工具可以使用,比如 QueryTask.

这里有与之前答案 link 相同的示例,但使用的是 QueryTask

<html>

<head>
  <meta charset='utf-8'>
  <meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no'>
  <title>Select Feature With Polygon</title>
  <style>
    html,
    body {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 400px;
      width: 100%;
    }
    #namesDiv {
      margin: 10px;
      height: 200px;
      width: 100%;
      font-style: italic;
      font-weight: bold;
      font-family: Arial, Helvetica, sans-serif;
      font-size: 16px;
      color: green;
      overflow: auto;
    }
  </style>

  <link rel='stylesheet' href='https://js.arcgis.com/4.15/esri/css/main.css'>
  <script src='https://js.arcgis.com/4.15/'></script>

  <script>
    require([
      'esri/Map',
      'esri/views/MapView',
      'esri/layers/MapImageLayer',
      'esri/layers/GraphicsLayer',
      'esri/widgets/Sketch/SketchViewModel',
      'esri/Graphic',
      'esri/widgets/Expand',
      'esri/tasks/QueryTask',
      'esri/tasks/support/Query'
    ], function (
      Map,
      MapView,
      MapImageLayer,
      GraphicsLayer,
      SketchViewModel,
      Graphic,
      Expand,
      QueryTask,
      Query
    ) {
      let highlight = null;

      const states = new MapImageLayer({
        url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer'
      });

      const queryTask = new QueryTask({
        url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2'
      });

      const polygonGraphicsLayer = new GraphicsLayer();

      const selected = new GraphicsLayer();

      const map = new Map({
        basemap: 'streets',
        layers: [states, polygonGraphicsLayer, selected]
      });

      const view = new MapView({
        container: 'viewDiv',
        map: map,
        center: [-75.1683665, 39.951817],
        zoom: 8
      });

      const sketchViewModel = new SketchViewModel({
        view: view,
        layer: polygonGraphicsLayer,
        pointSymbol: {
          type: 'simple-marker',
          color: [255, 255, 255, 0],
          size: '1px',
          outline: {
            color: 'gray',
            width: 0
          }
        }
      });

      sketchViewModel.on('create', function (event) {
        if (event.state === 'complete') {
          polygonGraphicsLayer.remove(event.graphic);
          selectFeatures(event.graphic.geometry);
        }
      });

      const namesDiv = document.getElementById('namesDiv');

      view.ui.add('select-by-polygon', 'top-left');
      const selectButton = document.getElementById('select-by-polygon');

      selectButton.addEventListener('click', function () {
        clearUpSelection();
        sketchViewModel.create('polygon');
      });

      function selectFeatures(geometry) {
        selected.removeAll();
        const query = new Query();
        query.returnGeometry = true;
        query.outFields = ['*'];
        query.geometry = geometry;
        queryTask
          .execute(query)
          .then(function (results) {
            const graphics = results.features.map(r => {
              r.symbol = {
                type: 'simple-fill',
                fill: 'none',
                outline: {
                  color: 'cyan',
                  width: 2
                }
              };
              return r;
            });
            selected.addMany(graphics);
            namesDiv.innerHTML = graphics.map(g => g.attributes.NAME).join(',');
          })
          .catch(errorCallback);
      }

      function clearUpSelection() {
        selected.removeAll();
        namesDiv.innerHTML = null;
      }

      function errorCallback(error) {
        console.log('error:', error);
      }

    });
  </script>
</head>

<body>
  <div id='viewDiv'>
    <div
      id="select-by-polygon"
      class="esri-widget esri-widget--button esri-widget esri-interactive"
      title="Select counties by polygon"
    >
      <span class="esri-icon-checkbox-unchecked"></span>
    </div>
  </div>
  <div id="namesDiv"></div>
</body>

</html>

最后,我把这个 link 留给文档,它很好地解释了所有的可能性、优点和缺点。