google-code-prettify

星期三, 2月 11, 2015

[ArcGIS Server API for JavaScript] 地圖中加入 圖層圖例 Legend


繼上次案件 [ArcGIS Server API for JavaScript] 地圖中加入 ArcGISDynamicMapServiceLayer 圖層 後,接下來的案件是 加入 圖例元件 Legend

口白:
流動的水沒有形狀,漂流的風找不到蹤跡,任何案件的 Coding 都取決於心
唯一看透真相的是,外表看似卜朧共,智慧卻低於常人的 名卜朧共 刻爛
(謎之音:把 Code 刻到爛簡稱刻爛)
Music:
#表升半音 []表高八度
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 5 4 3 4 2 6 4 5 [2] [1] #6 6 5 6
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 4 3 2 4 2 6 4 5 [2] #6 6 5 6
口白:
刻爛:真相只有一個!

延續了前案件[ArcGIS Server API for JavaScript] 地圖中加入 ArcGISDynamicMapServiceLayer 圖層
這次是在這篇的基礎上加入了,圖例元件 Legend

Html:
<!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">
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" rel="stylesheet" type="text/css"></link>
    <script src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js" type="text/javascript">
    </script>
    <title>Legend</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">    
    <script src="http://js.arcgis.com/3.12/"></script>
  </head>
  <body class="claro" expr:class='&quot;loading&quot; + data:blog.mobileClass' onload='prettyPrint();'>
    <!-- MenuBar div#navMenu -->
    <div data-dojo-type="dijit/MenuBar" id="navMenu">
      <div data-dojo-type="dijit/PopupMenuBarItem">
        <span>地圖</span>
        <div data-dojo-type="dijit/DropDownMenu" id="mapMenu">
          <div data-dojo-type="dijit/MenuItem" data-dojo-props="onClick:function(){alert('地圖操作')}">地圖操作</div>
        </div>
      </div>
    </div>
    <!-- MenuBar div#navMenu -->

    <div id="navToolbar" data-dojo-type="dijit/Toolbar" class="NavToolBar">
      <div data-dojo-type="dijit/form/Button" id="zoomin"  data-dojo-props="iconClass:'zoominIcon'">Zoom In</div>
      <div data-dojo-type="dijit/form/Button" id="zoomout" data-dojo-props="iconClass:'zoomoutIcon'">Zoom Out</div>
      <div data-dojo-type="dijit/form/Button" id="zoomfullext" data-dojo-props="iconClass:'zoomfullextIcon'">Full Extent</div>
      <div data-dojo-type="dijit/form/Button" id="zoomprev" data-dojo-props="iconClass:'zoomprevIcon'">Prev Extent</div>
      <div data-dojo-type="dijit/form/Button" id="zoomnext" data-dojo-props="iconClass:'zoomnextIcon'">Next Extent</div>
      <div data-dojo-type="dijit/form/Button" id="pan" data-dojo-props="iconClass:'panIcon'">Pan</div>
      <div data-dojo-type="dijit/form/Button" id="deactivate" data-dojo-props="iconClass:'deactivateIcon'">Deactivate</div>
    </div>

    <div id="mapDiv" 
         data-dojo-type="dijit/layout/ContentPane" 
         data-dojo-props="region:'center'" 
         style="padding:0">
    </div>

    <div data-dojo-type="dijit/layout/ContentPane" id="legendPane"
           data-dojo-props="title:'Legend', selected:true" class="LegendTool" >
      <div id="legendDiv"></div>
    </div>

  </body>
</html>
說明:
1. 引用 CSS:claro.css、esri.css 引用參考位置如下:
   <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
   <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">  為了中文化排版被擠壓 修改 CSS

2. 引用 Javascript 需插入  <script src="http://js.arcgis.com/3.12/"></script> 其中已包含了Dojo框架囉

3. <body> 標籤中 加入 class 樣式定義為 "claro" 如: <body class="claro">

4. 加入 div 區塊 當作 MenuBar,如:<div data-dojo-type="dijit/MenuBar" id="navMenu"></div>

5. 加入 div 區塊 當作 PopupMenuBarItem,將該物件放在 MenuBar Div 區塊內 如:
   <div data-dojo-type="dijit/PopupMenuBarItem">
   </div>
   給該選單名稱,則是在 PopupMenuBarItem div 區塊 內加入 <span>地圖</span> 來定義
   加入 div 區塊 當作 DropDownMenu,將該物件放在 PopupMenuBarItem Div 區塊內 如:
   <div data-dojo-type="dijit/DropDownMenu" id="mapMenu">
   </div>
   加入 div 區塊 當作 MenuItem,將該物件放在 DropDownMenu Div 區塊內 如:
   <div data-dojo-type="dijit/MenuItem" data-dojo-props="onClick:function(){alert('地圖操作')}">地圖操作</div>

6. 加入 div 區塊 當作 dijit/Toolbar 容器,並將 dijit/form/Button 物件放在 navToolbar Div 區塊內 如:
   <div id="navToolbar" data-dojo-type="dijit/Toolbar" class="NavToolBar">
     <div data-dojo-type="dijit/form/Button" id="zoomin"  data-dojo-props="iconClass:'zoominIcon'">Zoom In</div>
   ...略....
   </div>

7. 加入 div 區塊 當作地圖區塊,如:<div id="mapDiv"></div>

8. 加入 div 區塊 當作 legendPane 區塊,如:<div id="legendPane" ...略.../div>,並定義class="LegendTool"
   於 div 區塊 legendPane 中,加入 當作 legendDiv 區塊,如:<div id="legendDiv" ...略.../div>
   此 div 區塊 legendDiv 區塊,是用來展現 legend 用

CSS:
.esriScalebarLabel.esriScalebarLineLabel.esriScalebarSecondNumber {
  font-size: 11px;
  position: absolute;
  width: 50%;
  text-align: center;
  color: #666666;
  font: Verdana;
  font-weight: bolder;
  height: 5px;
  top: -1px;
}
html, body, #mapDiv {
  padding: 0;
  margin: 0;
  height: 100%;
}
.zoominIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_zoomin.png);
  width: 16px;
  height: 16px;
}

.zoomoutIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_zoomout.png);
  width: 16px;
  height: 16px;
}

.zoomfullextIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_fullextent.png);
  width: 16px;
  height: 16px;
}

.zoomprevIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_previous.png);
  width: 16px;
  height: 16px;
}

.zoomnextIcon 
{ 
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_next.png);
  width: 16px;
  height: 16px;
}

.panIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_pan.png);
  width: 16px;
  height: 16px;
}

.deactivateIcon 
{
  background-image: url(http://developers.arcgis.com/javascript/samples/toolbar_navigation/images/nav_decline.png);
  width: 16px;
  height: 16px;
}
.NavToolBar 
{
  width: 120px; position: absolute; z-index: 999; height: auto; top: 60px; right: 50px;
}
.LegendTool
{
  width: 200px; position: absolute; z-index: 999; height: 600px; top: 60px; left: 50px;
}
說明:
1. 定義 mapDiv 區塊的 CSS 樣式
2. 中文化 排版被擠壓 .esriScalebarLabel.esriScalebarLineLabel.esriScalebarSecondNumber 調整width 改成 50%
3. 定義 zoominIcon、zoomoutIcon、zoomfullextIcon、zoomprevIcon、zoomnextIcon、panIcon、deactivateIcon、NavToolBar 樣式,其中包含工具圖示
4. 定義 LegendTool 樣式,定義大小位置

JavaScript:
var map;
require([
  "esri/map",
  "dojo/parser",

  // Modules referenced by the parser
  "dijit/DropDownMenu",
  "dijit/MenuBar",
  "dijit/MenuBarItem",
  "dijit/MenuItem",
  "dijit/PopupMenuBarItem",

  // ArcGISDynamicMapServiceLayer 會使用到的模組 
  "esri/layers/ArcGISDynamicMapServiceLayer", // 加入 Arcgis Server 發布ArcGISDynamicMapServiceLayer圖層 Package
  // ArcGISDynamicMapServiceLayer 會使用到的模組 

  // Legend 會使用到的模組 
  "dojo/_base/array",       // 加入 dojo/_base/array Package 
  "esri/dijit/Legend",      // 加入 esri/dijit/Legend Package 
  // Legend 會使用到的模組 

  // Overview 會使用到的模組 
  "esri/dijit/OverviewMap", // 加入 Overview Package 
  // Overview 會使用到的模組 

  // Scalebar 會使用到的模組 
  "esri/dijit/Scalebar",    // 加入 Scalebar Package 
  // Scalebar 會使用到的模組 

  // navigation ToolBar 會使用到的模組 
  // "dojo/parser", navigation ToolBar 會使用到的模組 也會使用到前面已經宣告過就不重覆載入
  "esri/toolbars/navigation",
  "dojo/on",
  "dijit/registry",
  "dijit/Toolbar",              // 因為本身並沒有針對對應物件操作,故不設定 載入對應 變數
  "dijit/form/Button",          // 因為本身並沒有針對對應物件操作,故不設定 載入對應 變數
  // navigation ToolBar 會使用到的模組 

  "dojo/domReady!"
], function (
  Map,
  parser,

  DropDownMenu,
  MenuBar,
  MenuBarItem,
  MenuItem,
  PopupMenuBarItem,

  // ArcGISDynamicMapServiceLayer 會使用到的模組 對應變數
  ArcGISDynamicMapServiceLayer, // 加入 ArcGISDynamicMapServiceLayer 承接 對應 "esri/layers/ArcGISDynamicMapServiceLayer" ArcGISDynamicMapServiceLayer Package  變數
  // ArcGISDynamicMapServiceLayer 會使用到的模組 對應變數

  // Legend 會使用到的模組 對應變數
  arrayUtils,    // 加入 arrayUtils 承接 對應 "dojo/_base/array" Package  變數
  Legend,        // 加入 Legend 承接 對應 "esri/dijit/Legend" Package  變數
  // Legend 會使用到的模組 對應變數

  // OverviewMap 會使用到的模組 對應變數
  OverviewMap,   // 加入 OverviewMap 承接 對應 "esri/dijit/OverviewMap" OverviewMap Package  變數
  // OverviewMap 會使用到的模組 對應變數

  // Scalebar 會使用到的模組 對應變數
  Scalebar,      // 加入 Scalebar 承接 對應 "esri/dijit/Scalebar" Scalebar Package  變數
  // Scalebar 會使用到的模組 對應變數

  // navigation ToolBar 會使用到的模組 對應變數
  // parser,, navigation ToolBar 會使用到的模組 也會使用到前面已經宣告過就不重覆載入
  Navigation,
  on,        
  registry        
  // navigation ToolBar 會使用到的模組 對應變數 
   
  )
{
  parser.parse();

  var navToolbar;
  var layer;

  // 中文化 S
  //console.log(esri.bundle.widgets.scalebar);
  esri.bundle.widgets.scalebar = { ft: "英呎", km: "公里", mi: "英里", m: "公尺" }; // 目前無作用
  window.esri.dijit.Scalebar.prototype.localStrings.km = '公里';
  window.esri.dijit.Scalebar.prototype.localStrings.m = '公尺';
  window.esri.dijit.Scalebar.prototype.localStrings.mi = '英里';
  window.esri.dijit.Scalebar.prototype.localStrings.ft = '英呎';
  //console.log(domStyle.getComputedStyle(dojo.query('.esriScalebarLabel.esriScalebarLineLabel.esriScalebarSecondNumber')).width);
  //domStyle.set(dojo.query('.esriScalebarLabel.esriScalebarLineLabel.esriScalebarSecondNumber'), "width", "50%");
  /*
  esri.css 
  修改 .esriScalebarLabel.esriScalebarLineLabel.esriScalebarSecondNumber 
  width:10% 改 width:50%
  */
  //console.log(esri.bundle.widgets.scalebar);
  // 中文化 E

  map = new Map("mapDiv",
    {
      //center: [182367.85715, 2561474.641595]
      //zoom: 8,
      //basemap: "streets",
      //sliderStyle:'large'
      basemap:"satellite",
      center :[-97.031, 37.638],
      zoom   :4,
      //slider :false
    sliderStyle:'large'
    });

  layer = new esri.layers.ArcGISDynamicMapServiceLayer(
    'http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Net_Worth/MapServer', 
    {opacity: 1.0});
  //console.log('ArcGISDynamicMapServiceLayer');
  

  //add the legend
  map.on("layers-add-result", function (evt) {
    var layerInfo = arrayUtils.map(evt.layers, function (layer, index) {
      return { layer: layer.layer, title: layer.layer.name };
    });
    if (layerInfo.length > 0) {
      var legendDijit = new Legend({
        map: map,
        layerInfos: layerInfo
      }, "legendDiv");
      legendDijit.startup();
    }
  });
  //add the legend
  map.addLayers([layer]);
  
  
  // 加入 OverviewMap 地圖上顯示鷹眼 開始
  var overviewMapDijit = new OverviewMap({
    map: map,
    attachTo: "bottom-right",
    visible: true
  });
  overviewMapDijit.startup();
  // 加入 OverviewMap 地圖上顯示鷹眼 結束

  // 加入 scalebar 地圖上顯示比例尺 開始
  var scalebar = new Scalebar({
    map: map,
    // "dual" displays both miles and kilmometers
    // "english" is the default, which displays miles
    // use "metric" for kilometers
    scalebarUnit: "dual"
  });
  scalebar.hide();
  scalebar.show();
  // 加入 scalebar 地圖上顯示比例尺 結束

  navToolbar = new Navigation(map);
  on(navToolbar, "onExtentHistoryChange", extentHistoryChangeHandler);

  registry.byId("zoomin").on("click", function () {
    navToolbar.activate(Navigation.ZOOM_IN);
  });

  registry.byId("zoomout").on("click", function () {
    navToolbar.activate(Navigation.ZOOM_OUT);
  });

  registry.byId("zoomfullext").on("click", function () {
    navToolbar.zoomToFullExtent();
  });

  registry.byId("zoomprev").on("click", function () {
    navToolbar.zoomToPrevExtent();
  });

  registry.byId("zoomnext").on("click", function () {
    navToolbar.zoomToNextExtent();
  });

  registry.byId("pan").on("click", function () {
    navToolbar.activate(Navigation.PAN);
  });

  registry.byId("deactivate").on("click", function () {
    navToolbar.deactivate();
  });

  function extentHistoryChangeHandler () {
    registry.byId("zoomprev").disabled = navToolbar.isFirstExtent();
    registry.byId("zoomnext").disabled = navToolbar.isLastExtent();
  }

});

說明:
1. 定義 弱型別的變數 map
   .require 是 Dojo 方法,利用該方法,
   載入 esri/map、dojo/parser、dijit/DropDownMenu、MenuBar、MenuBarItem、MenuItem、PopupMenuBarItem、esri/dijit/Scalebar、dojo/domReady! 
   Navigation 瀏覽工具 需用到的模組 esri/toolbars/navigation,dojo/on,dijit/registry,
   Navigation 瀏覽工具 也需要 dojo/parser (載入模組不需重複載入)
   而 dijit/Toolbar,dijit/form/Button,因為本身並沒有針對對應物件操作,故不設定 載入對應 變數
   要加入 ArcGISDynamicMapServiceLayer 圖層,需用到的模組 esri/layers/ArcGISDynamicMapServiceLayer,
   根據 Dojo API 參考文件來說,
   載入模組後,需用一個 變數來接收該模組,以便於操作 
   例如 function(Map) {}  用一個 拋棄式的函數,
   裡面定義變數: Map、parser、DropDownMenu、MenuBar、MenuBarItem、MenuItem、PopupMenuBarItem、Scalebar,
   Navigation 定義對應變數: Navigation、on、registry。
   ArcGISDynamicMapServiceLayer 定義對應變數: ArcGISDynamicMapServiceLayer。        

2. function(Map...略...) {}  用一個 拋棄式的函數 裡面定義 map 變數,
   透過傳入的 Map 類別可以 宣告成一個 esri/map 的物件,其他載入的亦同方式
   parser.parse() 主要是將 dom 轉換成 dijit 物件或是 widget
   (new Map 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/map-amd.html )
   另外因為載入 ArcGISDynamicMapServiceLayer 圖層與 basemap 坐標系統可能會不一樣,故 new Map(...,OPTIONS),
   物件 OPTIONS 中,定義的center,要改成 Layer 坐標系統定義
   並且把 basemap、zoom(可以不用註解) 參數註解掉,原因是坐標系統不一致套疊會有問題,若是坐標系統一致則不須關掉
   定義 弱型別的變數 layer  並將他 建立成 esri.layers.ArcGISDynamicMapServiceLayer 物件
   (new ArcGISDynamicMapServiceLayer 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/arcgisdynamicmapservicelayer-amd.html" )
    ArcGISDynamicMapServiceLayer 範例 
    ArcGISDynamicMapServiceLayer 範例:Shake gesture recognition 
   Url 部分,就是設定 ArcGIS Server 發布服務的位置
   options 部分,就是針對載入圖層相關設定,例如:透明度:opacity,顯示與否:visible。
   定義 弱型別的變數 overviewMapDijit  並將他 建立成 esri/dijit/OverviewMap 物件
   (new overviewMapDijit 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/overviewmap-amd.html" )
   widget overviewmap 範例 
   定義 弱型別的變數 scalebar 並將他 建立成 esri/dijit/Scalebar 物件
   (new Scalebar 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/scalebar-amd.html )
   widget scalebar 範例 
   定義 弱型別的變數 navToolbar  並將他 建立成 esri/toolbars/navigation 模組 Navigation 物件
   (new navToolbar 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/navigation-amd.html )
   widget navToolbar 範例 
   on 是 Dojo 模組 dojo/on 的事件監測方法,利用該方法,捕捉操作事件
   (on 宣告方法 就要查 http://dojotoolkit.org/api/?qs=1.10/dojo/on )
   target 的 DOM 是 navToolbar,type 用來偵聽或擴展事件類型 onExtentHistoryChange,listener 發生事件所呼叫的函數 extentHistoryChangeHandler
   函數 extentHistoryChangeHandler 內,註冊防呆機制,確保在第一筆與最後一筆時不作動!
   registry 是 Dojo 模組 dijit/registry 的事件註冊方法,利用該方法,擴展操作事件
   (registry 宣告方法 就要查 registry  宣告方法 就要查 http://dojotoolkit.org/api/?qs=1.10/http://dojotoolkit.org/api/?qs=1.10/dijit/registry )

3. Legend 宣告載入一樣是放在 function(Map...略...) {}  中,用一個 主要是透過 map.on 建立一個事件,
   (而 map 宣告方法  Class:Map 並沒有找到該函數 map.on)
   該方法推論是繼承 on 精神(使用方法不同),宣告方法 就要查 dojo/on 
   在 events 的說明,就把 物件.on 當成是一種事件監測器的方法來使用吧!
   透過 map.on 建立一個 layers-add-result 事件處理方法
   使用一個拋棄式函數,來取得加入 map 圖層的 layerInfo 屬性
   定義 弱型別的變數 legendDijit  並將他 建立成 legendDijit 模組 legend 物件
   (new legend 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/legend-amd.html )
    legend 範例 

JSBin Demo(http://goo.gl/ajbL32)

參考文獻︰
events
legend
legend 範例


沒有留言 :

張貼留言