ArcGIS API for JavaScript 4.2學習筆記[21] 對3D場景上的3D要素進行點擊查詢【Query類學習】


有人問我怎么這個系列沒有寫自己做的東西呢?

大哥大姐,這是“學習筆記”啊!當然主要以解讀和筆記為主咯。

也有人找我要實例代碼(不是示例),我表示AJS尚未成熟,現在數據編輯功能才簡略地在AJS 4.3中出現,4.2是沒有的,widget和分析功能也不是很完善,還是再等等吧,先學着基礎,其他的以后再說。

本節我會緊隨這個例子學習一下Query這個類,作為圖層查詢方法的重要參數,它起了傳遞查詢用的信息的作用。


本例對應官方的例子是:Query a SceneLayer's linked FeatureLayer

這個例子操作起來很簡單,等地圖加載完成后,點擊對應的3D白色模型,會出現一個popupTemplate彈窗,顯示一個表格,為這個大樓的信息。如下圖:

換個視角:

那我們就開始吧!


 

給出引用

require([
  "esri/Map",
  "esri/views/SceneView",
  "esri/layers/SceneLayer",
  "esri/layers/FeatureLayer",
  "esri/tasks/support/Query",
  "dojo/domReady!"
  ],
   function(Map, SceneView, SceneLayer, FeatureLayer, Query){
    ...
    }
)

數據方面,用到了場景圖層和要素圖層;

查詢方面,用到了Query模塊。

函數參數

function(Map, SceneView, SceneLayer, FeatureLayer, Query){
    var map = new Map({...});
    var view = new SceneView({...});
    var sceneLayer = new SceneLayer({...});
    map.add(sceneLayer);
    var featureLayer = new FeatureLayer({...});
    featureLayer.load().then(attributesReady);
    function attributesReady(){
      ...  
    }
}

套路,先把大骨架弄出來,然后逐個擊破。

多了一個場景圖層,多了一個要素圖層,在要素圖層加載完成后進行一個異步操作attributesReady()。

還算簡單,先把map和view的代碼看看(太基礎了對於看到這里的人來說,我就縮起來了)

var map = new Map({
  basemap: "dark-gray",
  ground: "world-elevation"
});
var view = new SceneView({
  container: "viewDiv",
  map: map,
  camera: {
    position: {
      x: -8241580,
      y: 4964925,
      z: 2311,
      spatialReference: 3857
    },
    heading: 32.5,
    tilt: 64.9
  }
});
map和view

對於view,可以看到除了camera屬性外還多了兩個屬性,這里不作為重點,可以參考API。

看看兩個layer:

var sceneLayer = new SceneLayer({
  url: "https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/New_York_LoD2_3D_Buildings/SceneServer/layers/0",
  popupEnabled: false
});

map.add(sceneLayer);

var featureLayer = new FeatureLayer({
  url: "https://services2.arcgis.com/z2tnIkrLQ2BRzr6P/arcgis/rest/services/New_York_OBJECTID/FeatureServer/0",
  outFields: ["*"],
  popupTemplate: {
    title: "...",
    content: [{type: "fields"}],
    fieldInfos: [{...}, {...}, {...}, {...}]
  }
});

在我的理解中,sceneLayer應該是綠色的圓錐體,而featureLayer則是用於支持空間查詢的數據圖層。看得出這里都是使用了ArcGIS Server上的服務。

featureLayer的彈窗模板較為復雜,不是這里討論的內容,我就把源代碼換成了省略號以精簡頁面,大概意思就是從featureLayer中獲取fields作為彈窗的content,而fieldInfos則是對應字段的輸出格式。

重點應該是下面這個方法體:

featureLayer.load().then(attributesReady);

function attributesReady() {
    view.on("click", function(event){
        var screenPoint = {...};
        view.hitTest(screenPoint)
.then(
function(response){...}) .then(function(graphic){...}) .then(function(results){...}) .otherwise(function(err){...}) }) }

逐個擊破,首先是的view的click事件,觸發該事件后立刻獲取當前點擊的點screenPoint,並將點傳遞到hitTest方法中,緊接着就是四層異步操作。

第一層:

.then(function(response) {
      var result = response.results[0];
      if (result && result.graphic) {
          return result.graphic;
      }
})

似乎是獲取results[0]后判斷其是否為空或者其幾何屬性是否為空,如果不是空,返回其幾何屬性。

這里就要查一下了,這個response 是什么東西?而results[0]又是什么?

通過查閱SceneView的hitTest()方法,可以得知results[0]也就是result變量就是hitTest的返回值。

該result變量擁有兩個屬性,一個是mapPoint,為Point類型;

另一個是graphic,為Graphic類型。

前一個屬性代表了點擊的那個點位置,后面則為點擊的要素的幾何體。

如果都不為空,返回幾何體,傳入下一個then:

.then(function(graphic) {
  var objectid = graphic.attributes.objectid;
  var query = new Query();
  //設置query的參數
  query.where = "objectid = " + objectid;
  query.returnGeometry = false;
  query.outFields = ["NAME", "CNSTRCT_YR", "LSTMODDATE",
    "LSTSTATYPE", "NUM_FLOORS"
  ];
  //執行查詢
  return featureLayer.queryFeatures(query);
})

傳入的graphic,獲取其objectid屬性

然后實例化一個Query對象名為query,設置好where查詢語句(應該是SQL語句吧)、是否返回幾何體(否)、輸出字段信息,就可以執行查詢。

featureLayer的queryFeatures()方法接受Query對象,返回一個類型為FeatureSet的Promise對象。

這個FeatureSet對象傳遞給下一個then:

.then(function(results) {
  if (results && results.features.length > 0) {
    view.popup.open({
      features: results.features,
      location: event.mapPoint
    });
  }
})
.otherwise(function(err) {
  console.error(err);
});

不要放棄啊!

因為馬上后面就沒有代碼了~那個otherwise只是Promise對象除了then之外的另一個而已~出錯了就用otherwise來處理異常~

這個then,如果傳入的FeatureSet不為空或者FeatureSet里面的features個數>0

那么就按照featureLayer里寫好的格式彈窗顯示信息~完事。


總結一下

這個例子就是獲取點擊點——使用query對象進行空間查詢——返回FeatureSet——輸出其預置好的Popup即可~

沒有上一個那么難了吧~~~

文章的最后,我來對Query這個對象進行學習:

Query對象的學習

查詢API得知:

 

繼承自Accessor,分類在esri/tasks/support/Query下。

需要注意的是,使用Query類需要在ArcGIS Online或者ArcGIS Server服務的支持下進行。

 

翻譯官方的解釋,意思就是:

Query對象是一些空間查詢的參數,它作用於layer對象,通過參數的設置,可以篩選出layer中需要的要素。

可以使用QueryTask類的excute()方法進行空間查詢,也可以在圖層實例的queryFeatures()方法中使用Query對象。

使用它,通常返回結果是FeatureSet對象。

Query類擁有非常多的參數,方法只有一個toJSON(),這個方法是將這個類的實例序列化成JSON而存在的,不做重點介紹。

參數就摘幾個吧:

distance(Number類型)、geometry(Geometry類型)、num(Geometry類型)、outFields(String[])、outSpatialReference(SpatialReference)、returnGeometry(Boolean)、units(String)、where(String)

distance是緩沖區分析的距離;

geometry是用於空間查詢用的幾何體;

num是查詢得到的要素個數;

outFields是查詢結果要素集的字段信息;

outSpatialReference是查詢結果要素集的空間參考信息;

returnGeometry是一個布爾變量,如果為真,那么返回的要素集中每一個要素就會包含幾何體;

units是緩沖區分析的單位;

where是空間查詢用的SQL語句。如:query.where = "NAME = '" + stateName + "'";

如何用它呢?

給個簡單的例子,使用QueryTask的(接下來幾篇博文會用到這個):

require(["esri/tasks/QueryTask", "esri/tasks/support/Query"], function(QueryTask, Query){
  //用URL實例化一個QueryTask,應該是一個服務類型
  var queryCitiesTask = new QueryTask({
    url: "..."  
  });
  //實例化一個Query對象
  var query = new Query();
  query.geometry = mapPoint; 
  query.distance = 100;
  query.units = "miles";
  query.spatialRelationship = "intersects";
  queryCitiesTask.execute(query).then(function(result){
      //對返回的FeatureSet進行操作
  });
});

如果是圖層的queryFeatures()方法,各位看官請往上翻一翻啦~

 

ps:轉載請注明出處。http://www.cnblogs.com/onsummer/p/6421503.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM