【官方文檔:https://developers.arcgis.com/javascript/latest/sample-code/intro-layers/index.html】
一、Intro to layers
地圖是由許多圖層構成的,圖層(layer)是地圖的重要組件,通過展示空間數據來表現實際生活現象。圖層可以表示矢量要素(vector),也可以表示柵格要素(raster)。JS API中可以使用很多種類的圖層(layer),具體類別請查看文檔:https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-Layer.html#layer-types。
1.代碼骨架
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <!-- 移動端優化 --> 6 <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> 7 <title>Intro to layers</title> 8 9 <!-- JS API的引入 --> 10 <link rel="stylesheet" href="https://js.arcgis.com/4.8/esri/css/main.css"> 11 <script src="https://js.arcgis.com/4.8/"></script> 12 13 <script> 14 15 </script> 16 17 <!-- 設置樣式,正確顯示地圖 --> 18 <style> 19 html,body,#viewDiv{ 20 padding:0; 21 margin:0; 22 height:100%; 23 width:100%; 24 } 25 </style> 26 </head> 27 28 <body> 29 <div id="viewDiv"></div> 30 </body> 31 </html>
其中包括,JS API的引入、style樣式的設置等等。
2.創建地圖(Map)和3D視圖(SceneView)
1 <script> 2 require([ 3 "esri/Map", 4 "esri/views/SceneView", 5 "dojo/domReady!" 6 ],function(Map,SceneView){ 7 // 創建地圖 8 var map=new Map({ 9 basemap:"oceans" 10 }); 11 12 // 創建SceneView 13 var view=new SceneView({ 14 container:"viewDiv", 15 map:map 16 }); 17 }); 18</script>
3.創建切片圖層(TileLayer)
每一個圖層(layer)都有一個url屬性,這個url可以來自ArcGIS Server發布的服務或者是portal中的地圖內容。不同的url標識不同的圖層,每個圖層都只有唯一的url。這里使用Esri World Transportation service提供的地圖服務。
1 <script> 2 require([ 3 "esri/Map", 4 "esri/views/SceneView", 5 "esri/layers/TileLayer", // 需要新添加的模塊 6 "dojo/domReady!" 7 ],function(Map,SceneView,TileLayer){ // 注意這里也需要添加對應的類 8 // 創建地圖 9 var map=new Map({ 10 basemap:"oceans" 11 }); 12 13 // 創建SceneView 14 var view=new SceneView({ 15 container:"viewDiv", 16 map:map 17 }); 18 19 var transportationLayer=new TileLayer({ 20 url:"https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer", 21 id:"streets", // 設置其他一些屬性 22 opacity:0.7 23 }); 24 25 var housingLayer=new TileLayer({ 26 url:"https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Housing_Density/MapServer", 27 id:"ny-housing" 28 }); 29 }); 30</script>
"esri/layer/TileLayer"是新添加的模塊,在function()也要添加相應的類。
創建兩個TileLayer切片圖層,設置相應url和其他相關屬性,url由Esri提供。id是對圖層的標識,opacity設置圖層的透明度。還有一些屬性,比如minScale和maxScale控制圖層在不同比例尺下的可見性,以增強圖層在地圖上的表達合理性。visible屬性為true顯示圖層,為false使圖層不可見。
4.添加圖層到地圖
將創建好的圖層添加到地圖上有很多種方式,具體請查看文檔:https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html#layers。
這里給出兩種方式:①在Map構造函數中設置相關屬性 ②通過Map實例的方法添加
第一種方法:在Map構造函數中設置layers屬性以添加相應圖層(這種方法未成功實現)
1 var map=new Map({ 2 basemap:"oceans", 3 layers:[housingLayer] // 設置的屬性 4 });
但是運行結果報錯,錯誤信息如下:
(更新:這種方法是可行的,之前報錯是因為housingLayer在實例化Map之后才定義,相當於給layers屬性添加了一個未定義的圖層)
第二種方法:通過Map實例的方法添加
1 map.layers.add(housingLayer); 2 map.layers.add(transportationLayer);
這樣就將之前創建的圖層添加到了底圖上,最終運行效果如下。可以看到交通線和紐約地區的城市面都已添加到底圖Oceans上。
5.在頁面中控制圖層的顯示與隱藏
在<body>中添加checkbox控件。注意checkbox的id,后面會用到。
1 <body> 2 <div id="viewDiv"> 3 <span id="layerToggle"> 4 <input type="checkbox" id="streetsLayer" checked>Transportation 5 </span> 6 </div> 7</body>
當點擊checkbox時,會觸發change事件,以控制圖層的visible屬性。監聽change事件需要導入"dojo/on"模塊和"dojo/dom"模塊。"dojo/on"用於監聽HTML DOM上的事件,"dojo/dom"用於獲得DOM元素。
1 <script> 2 require([ 3 "esri/Map", 4 "esri/views/SceneView", 5 "esri/layers/TileLayer", // 需要新添加的模塊 6 "dojo/dom", // 用於獲取HTML DOM元素 7 "dojo/on", // 用於監聽HTML DOM元素上的事件 8 "dojo/domReady!" 9 ],function(Map,SceneView,TileLayer,dom,on){ // 注意這里也需要添加對應的類 10 // 創建地圖 11 var map=new Map({ 12 basemap:"oceans", 13 }); 14 15 // 創建SceneView 16 var view=new SceneView({ 17 container:"viewDiv", 18 map:map 19 }); 20 21 var transportationLayer=new TileLayer({ 22 url:"https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer", 23 id:"streets", // 設置其他一些屬性 24 opacity:0.7 25 }); 26 27 var housingLayer=new TileLayer({ 28 url:"https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Housing_Density/MapServer", 29 id:"ny-housing", 30 31 }); 32 33 map.layers.add(housingLayer); 34 map.layers.add(transportationLayer); 35 36 // 獲取checkbox元素,通過dom.byId()方法 37 var streetsLayerToggle=dom.byId("streetsLayer"); 38 39 // 監聽checkbox的change事件 40 on(streetsLayerToggle,"change",function(){ 41 // 當checkbox為true時,圖層的visible也為true 42 transportationLayer.visible=streetsLayerToggle.checked; 43 }); 44 }); 45</script>
通過dojo提供的dom.byId()方法獲取checkbox元素。使用dojo提供的on()方法對checkbox改變狀態這一事件進行監聽,並設置響應行為。on()有3個參數,第一個參數是監聽的對象,這里是指向checkbox的那個變量。第二個參數是監聽事件,這里是"change"。第三個參數是一個匿名函數,即事件發生時的響應行為。這里是將transportationLayer圖層的可見性設置成checkbox的狀態屬性,以起到顯示圖層與隱藏圖層的功能。
這里要注意,當圖層的visible屬性為false時,它仍是Map地圖的一部分,仍添加在這個地圖中,只是看不見而已,但它是存在的。依然可以訪問這個圖層的屬性,或使用這個圖層進行一些分析操作。
現在通過勾選checkbox,以進行transportationLayer圖層的顯示與隱藏。
6.理解圖層視圖(LayerView)
圖層(layer)是發布的地圖服務,包含着地理數據和屬性數據的信息。當圖層在視圖View中加載完成時,會創建一個LayerView。可以理解成View之下顯示layer的一個東西。當圖層加載完成時(即LayerView創建時),會觸發視圖View的"layerview-create"事件。下面為function(){}中添加的代碼。
1 // 圖層加載完成時將生成LayerView 2 // 將觸發View的"layerview-create"事件 3 view.on("layerview-create",function(event){ 4 if(event.layer.id==="ny-housing"){ 5 // 加載的是housingLayer 6 console.log("LayerView for New York housing density created!",event.layerView); 7 }; 8 if(event.layer.id==="streets"){ 9 // 加載的是transportationLayer 10 console.log("LayerView for streets created!",event.layerView); 11 }; 12 });
當view的"layerview-create"事件觸發后,進行layer.id的判斷以顯示相對應的信息。
7.使用Layer.when()
一個圖層(layer)就是一個promise(promise的詳細概念請參考文檔:https://developers.arcgis.com/javascript/latest/guide/working-with-promises/index.html)
Layer.when()方法的作用是當圖層加載完成后,再進行一些行為。這里,當housing layer加載完成后,想要讓地圖縮放到適合的比例尺及這個圖層所在的地區(紐約地區)。在function(){}中添加如下代碼。
1 // 當housing layer加載完成后,縮放到這個圖層的fullExtent 2 housingLayer.when(function(){ 3 view.goTo(housingLayer.fullExtent); 4 });
view.goTo()是將視角移到別的地方。
這樣設置后,頁面先顯示出整個地球,接着跳到紐約那邊圖層區域。
8.最終代碼
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <!-- 移動端優化 --> 6 <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> 7 <title>Intro to layers</title> 8 9 <!-- JS API的引入 --> 10 <link rel="stylesheet" href="https://js.arcgis.com/4.8/esri/css/main.css"> 11 <script src="https://js.arcgis.com/4.8/"></script> 12 13 <script> 14 require([ 15 "esri/Map", 16 "esri/views/SceneView", 17 "esri/layers/TileLayer", // 需要新添加的模塊 18 "dojo/dom", // 用於獲取HTML DOM元素 19 "dojo/on", // 用於監聽HTML DOM元素上的事件 20 "dojo/domReady!" 21 ],function(Map,SceneView,TileLayer,dom,on){ // 注意這里也需要添加對應的類 22 // 創建地圖 23 var map=new Map({ 24 basemap:"oceans", 25 }); 26 27 // 創建SceneView 28 var view=new SceneView({ 29 container:"viewDiv", 30 map:map 31 }); 32 33 var transportationLayer=new TileLayer({ 34 url:"https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer", 35 id:"streets", // 設置其他一些屬性 36 opacity:0.7 37 }); 38 39 var housingLayer=new TileLayer({ 40 url:"https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Housing_Density/MapServer", 41 id:"ny-housing", 42 43 }); 44 45 map.layers.add(housingLayer); 46 map.layers.add(transportationLayer); 47 48 // 獲取checkbox元素,通過dom.byId()方法 49 var streetsLayerToggle=dom.byId("streetsLayer"); 50 51 // 監聽checkbox的change事件 52 on(streetsLayerToggle,"change",function(){ 53 // 當checkbox為true時,圖層的visible也為true 54 transportationLayer.visible=streetsLayerToggle.checked; 55 }); 56 57 // 圖層加載完成后將生成LayerView 58 // 將觸發View的"layerview-create"事件 59 view.on("layerview-create",function(event){ 60 if(event.layer.id==="ny-housing"){ 61 // 加載的是housingLayer 62 console.log("LayerView for New York housing density created!",event.layerView); 63 }; 64 if(event.layer.id==="streets"){ 65 // 加載的是transportationLayer 66 console.log("LayerView for streets created!",event.layerView); 67 }; 68 }); 69 70 // 當housing layer加載完成后,縮放到這個圖層的fullExtent 71 housingLayer.when(function(){ 72 view.goTo(housingLayer.fullExtent); 73 }); 74 }); 75 </script> 76 77 <!-- 設置樣式,正確顯示地圖 --> 78 <style> 79 html,body,#viewDiv{ 80 padding:0; 81 margin:0; 82 height:100%; 83 width:100%; 84 } 85 </style> 86 </head> 87 88 <body> 89 <div id="viewDiv"> 90 <span id="layerToggle"> 91 <input type="checkbox" id="streetsLayer" checked>Transportation 92 </span> 93 </div> 94 </body> 95 </html>
關於Layer的更多信息,請參考文檔:https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-Layer.html