google-code-prettify

星期三, 1月 14, 2015

[ArcGIS Server API for JavaScript] 套疊 WMS



話說 WMS 要怎麼樣 "套"誤(怎麼老是想用套,框架工具才會是套用,圖層是用疊的)   "疊"上去呢?
ArcGIS Server API for JavaScript 參考 Sample Code:WMS - resource info (http://goo.gl/lbMdfN) 教的程式吧!
照著Sample Code 教學 刻一次吧!

Html:
<!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>Map with WMS</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">
    <div id="content"
         data-dojo-type="dijit.layout.BorderContainer"
         data-dojo-props="design:'headline', gutters:true"
        style="width: 100%; height: 100%; margin: 0;">
      <div id="details"
           data-dojo-type="dijit.layout.ContentPane"
           data-dojo-props="region:'left', splitter:true"
           style="overflow:auto; width:200px;">
      </div>
      <div id="map"
           data-dojo-type="dijit.layout.ContentPane"
           data-dojo-props="region:'center'"
           style="overflow:hidden;">
      </div>
    </div>
  </body>
</html>

說明:
1. 引用 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">
2. 引用 Javascript 需插入  <script src="http://js.arcgis.com/3.12/"></script> 其中已包含了Dojo框架囉
3. <body> 標籤中 加入 class 樣式定義為 "claro" 如: <body class="claro">
4. 加入 div 區塊 當作地圖區塊 ,如:<div id="map"></div>,
    並且定義:data-dojo-type="dijit.layout.ContentPane"、data-dojo-props="region:'center'";
    data-dojo-type、data-dojo-props這兩個是什麼東西呢?(沒有人會回答我吧!出來Code!遲早要還的!)
    這兩個就把它當成是Dojo 物件 自訂的屬性來看吧!
    根據百度(http://goo.gl/W53NWQ) 找到的說法:data-dojo-props 用來設置 dojo widget 的屬性,
    data-dojo-type 用來設置 dojo widget 的類型
    根據 Dojo 文件(http://goo.gl/Bs2n0I) 說的,dijit/layout/ContentPane 是一個最基本的設計磚塊(是哪招?這年頭要越獄就怕的就是遇到磚...還是把網頁當成蓋房子嗎?難怪叫道場)

CSS:
    html, body, #mapDiv {
      padding: 0;
      margin: 0;
      height: 100%;
    }
說明:
1. 定義 map 區塊的 CSS 樣式

JavaScript:
    var map;
    require([
      'esri/map', 'esri/layers/WMSLayer', 'esri/layers/WMSLayerInfo', 'esri/geometry/Extent',
      'dojo/_base/array', 'dojo/dom', 'dojo/dom-construct', 'dojo/parser',
      'dijit/layout/BorderContainer', 'dijit/layout/ContentPane', 'dojo/domReady!'
    ], function(Map, WMSLayer, WMSLayerInfo, Extent, array, dom, domConst, parser) {
      parser.parse();

      map = new Map('map', {
        basemap: 'streets',
        center: [-96, 37],
        zoom: 4
      });

      var layer1 = new WMSLayerInfo({
        name: '1',
        title: 'Rivers'
      });
      var layer2 = new WMSLayerInfo({
        name: '2',
        title: 'Cities'
      });
      var resourceInfo = {
        extent: new Extent(-126.40869140625, 31.025390625, -109.66552734375, 41.5283203125, {
          wkid: 4326
        }),
        layerInfos: [layer1, layer2]
      };
      var wmsLayer = new WMSLayer('http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer', {
        resourceInfo: resourceInfo,
        visibleLayers: ['1', '2']
      });
      map.addLayers([wmsLayer]);

      var details = dom.byId('details');
      domConst.place('<b>Layers</b>:', details);
      var ul = domConst.create('ul', null, details);
      array.forEach(wmsLayer.layerInfos, function(layerInfo) {
        domConst.create('li', { innerHTML: layerInfo.title }, ul);
      });
      domConst.place('<b>WMS Version</b>:' + wmsLayer.version + '<br />', details);
    });
說明:
1. 定義 弱型別的變數 map
    require 是 Dojo 方法,利用該方法 載入'esri/map', 'esri/layers/WMSLayer', 'esri/layers/WMSLayerInfo', 'esri/geometry/Extent', 'dojo/_base/array', 'dojo/dom', 'dojo/dom-construct', 'dojo/parser', 'dijit/layout/BorderContainer', 'dijit/layout/ContentPane', 'dojo/domReady!'

2. 載入模組後,需用定義對應的變數來接收該模組,
    Map, WMSLayer, WMSLayerInfo, Extent, array, dom, domConst, parser

3. function(Map) {}  用一個 拋棄式的函數 裡面定義 map 變數,
    透過傳入的 Map 類別可以 宣告成一個 esri/map 的物件
    (new Map 宣告方法 就要查 https://developers.arcgis.com/javascript/jsapi/map-amd.htmlnew Map(divId, options?)  第一個參數是 divId ,
    所以要對應 html 中 要顯示地圖 的 div ID(<div id="map"..略),
    第二個參數是個 Object ,範例中所定義的屬性有 basemap、center、zoom,
    basemap(我稱它叫基本底圖) 它有的選項︰ "streets" , "satellite" , "hybrid", "topo", "gray", "dark-gray", "oceans", "national-geographic", "terrain" 和 "osm";
    center(預設地圖顯示中心點位置):它是一個矩陣,例如: [-96, 37];
    zoom(初始地圖顯示範圍層級):它是一個整數,例如:zoom: 4

4. 定義了兩個 WMSLayerInfo 變數 ,並定義它為 WMSLayerInfo(http://goo.gl/NOnzHh) 物件,
    new WMSLayerInfo(layer) 參數是個 Object ,範例中所定義的屬性有 name 、title
    name (Layer 名稱,要對應WMS名稱或者index);
    title (Layer 標題,可以自行定義)

5. 定義 Object 變數 resourceInfo,目的是之後宣告 wmsLayer 變數時 Option 屬性 Object 會使用到
    其中有兩個屬性 extent、layerInfos,
    而 extent屬性 需定義一個 extent(http://goo.gl/HEZmf8) 物件,
    並定義 座標參考 spatialreference 物件 [標準:spatialreference(http://goo.gl/qgM3sy) ],
    而 layerInfos屬性 需是要給一個 WMSLayerInfo 矩陣,

6. 定義 WMSLayer(http://goo.gl/Rup72F) 變數 wmsLayer,
    new WMSLayer(url, options?) ,其中有兩個屬性 url(WMS 網址) 、options(Object 屬性參數)
    Option 屬性 又是一個 Object ,裡面則用到了兩個屬性 resourceInfo、visibleLayers ,
    resourceInfo 屬性,則是承接 之前所定義的 Object 變數 resourceInfo,
    visibleLayers 屬性,則是定義一個矩陣,矩陣內容釋放要顯示的圖層 name ,例如:['1', '2']
    (這樣寫我以後看的懂嗎?)

7. 把圖層加入 map 語法:map.addLayers([wmsLayer])

8. 之後的程式碼一句話帶過吧!只是為了顯示圖層 title 與 wms 版本

JSBin Demo(http://goo.gl/QQs9oZ)
JSBin Demo(http://goo.gl/Il7MdM) 介接國土測繪中心通用版電子地圖WMS EMAP

另外一種方式 Custom layer - WMS ,改天再來實作吧!


5 則留言 :

  1. 你好 我有看到你有介接國土測繪中心的電子地圖 我也試著去連結過 不過都會失敗
    我的主要的code如下:

    map = new Map('map', {
    basemap: 'streets',
    center: [120.58, 23.58],
    zoom: 7
    });

    var layer1 = new WMSLayerInfo({
    name: 'EMAP2',
    title: 'EMAP2'
    });
    var layer2 = new WMSLayerInfo({
    name: 'EMAP5_OPENDATA',
    title: 'EMAP5_OPENDATA'
    });
    var resourceInfo = {
    extent: new Extent(120.0000, 21.4300, 122.0000, 26.3600, {
    wkid: 3826
    }),
    layerInfos: [layer1, layer2]
    };
    var wmsLayer = new WMSLayer('http://maps.nlsc.gov.tw/S_Maps/wms', {
    resourceInfo: resourceInfo,
    visibleLayers: ['1','2']
    });
    map.addLayers([wmsLayer]);

    我的猜想是在extent 和 wkid 設定錯誤 不知道您是否能指導一下我 這個問題該如何解決呢 ?

    回覆刪除
    回覆
    1. 您好:
      我看到的錯誤:
      1. epsg:3826是TWD97/TM2 座標系統...您給的extent是經緯度...
      2.我是接emap
      var layer1 = new WMSLayerInfo({name: 'EMAP',title: '通用版電子地圖'});
      var resourceInfo = {extent: new Extent(146336.773, 2370779.874, 370123.966, 2851009.937, { wkid: 3826}),layerInfos: [layer1]
      };
      var wmsLayer1 = new WMSLayer('http://maps.nlsc.gov.tw/S_Maps/wms', {
      resourceInfo: resourceInfo,
      visibleLayers: ['EMAP']
      });
      3.版本定義要正確
      wmsLayer1.version='1.1.1';
      4.我沒有挑...
      map.addLayers([wmsLayer1]);


      ps. WMSLayerInfo 接 wms
      我發現他有個特性就是他只認識他發出來的座標系統,
      如果底圖座標系統跟他不一樣他也會看不到圖...也許圖會出現在阿爾及利亞...
      (我也不熟,台灣的代理商就像水貨商一樣,我們只能靠自己了,或許請總代理協助會好一點)

      另外您可以把code寫在jsbin、jsfiddle、codepen等的線上前端開發工具平台,
      這樣比較容易看你現況,發在這,我只能用猜的...不知道能不能幫到你

      刪除
  2. 請問為什麼通用版電子地圖的程式看不懂?編碼過嗎

    回覆刪除
    回覆
    1. 您說的jsbin上的嗎?jsbin 上有編譯過
      上面JavaScript是有問題的
      map = new Map('map', {basemap: 'streets',center: [-96, 37],zoom: 4});
      var layer1 = new WMSLayerInfo({...略...});
      var resourceInfo = {...略...};
      var wmsLayer = new WMSLayer(...略...);

      map = new Map('map', {center: [120.58, 23.58],zoom: 8});
      var layer1 = new WMSLayerInfo({name: 'EMAP',title: '通用版電子地圖'});
      var resourceInfo = {extent: new Extent(146336.773, 2370779.874, 370123.966, 2851009.937, { wkid: 3826}),layerInfos: [layer1]
      var wmsLayer = new WMSLayer('http://maps.nlsc.gov.tw/S_Maps/wms', {resourceInfo: resourceInfo,visibleLayers: ['EMAP']});
      接著補下面這段
      wmsLayer.version='1.1.1';
      不補的話會被當1.3.0去,接然後就白白的一片

      jsbin:https://output.jsbin.com/luruvisaxi/1


      openstreetmap不是3826...國土那邊出來是3826 這個物件如果不是相同坐標系統就會接不上,我試出來是這樣的

      不要研究這個,這個不好用

      刪除
    2. 原來是這樣...我用arcgis3X去接97的WMTS會偏移
      但是用4X的去接就不會...非常神奇
      所以才會想說改接WMS好了
      感謝你

      刪除