GIS奮闘記

現役GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

ArcGIS API for JavaScript でレイヤーの表示/非表示を行う方法

さて、本日も ArcGIS API for JavaScript について書いてみようと思います。前回は以下エントリーでウィジェットについて紹介したのですが、今回はレイヤー表示の切り替えについて書いてみようと思います。

www.gis-py.com

実行環境

ArcGIS API for JavaScript 4.12
Chrome

今回のポイントとなる処理

  1. レイヤーの表示
  2. レイヤーのスケールフィルタの設定
  3. レイヤーの透明度の設定
  4. 初期表示の設定
  5. レイヤーの表示/非表示の制御
  6. レイヤー一覧ボタンの配置

ざっとこんなところでしょうか。色々あるのですが、どれも難しい処理ではありません。

完成イメージ

初期表示は以下のような感じです。
f:id:sanvarie:20191012120012p:plain

「レイヤー一覧」ボタンを押すとレイヤー一覧が表示されます。
f:id:sanvarie:20191012120037p:plain

レイヤをすべて非表示にした状態です。ベースマップのみが表示されている状態になります。
f:id:sanvarie:20191012120058p:plain

各処理について

各処理のポイントを以下で解説します。

レイヤ-の表示

以下のようにすればレイヤーの表示を行うことができます。var map = new Map({basemap: "gray-vector"}); でマップのオブジェクトを作成します。その後に各レイヤのオブジェクトを作成し、それぞれ map.add(); します。そして、作成したマップをパラメーターにして var view = new MapView({ }); でマップビューのオブジェクトを作成します。

var map = new Map({
    basemap: "gray-vector"
});

var vectorTileLayer = new VectorTileLayer({
    url:
    "https://www.arcgis.com/sharing/rest/content/items/92c551c9f07b4147846aae273e822714/resources/styles/root.json",
    id:"vectorTile"
});

var mapImageLayer = new MapImageLayer({
    url: "https://content.esrij.com/arcgis/rest/services/Dosyasaigai/Dosyasaigai_Tile/MapServer",
    id:"mapImage"
});

var boundary = new FeatureLayer({
    url:"https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/JPN_Boundaries_ECM/FeatureServer",
    id:"boundary",
    opacity:0.5,
    minScale:1500000,
    maxScale:50000
});

map.add(vectorTileLayer);
map.add(mapImageLayer);
map.add(boundary);

var view = new MapView({  
    container: "viewDiv",
    map: map,
    center: [139.740286, 35.678601],
    zoom: 15
});

レイヤーのスケールフィルタの設定

minScale:1500000,
maxScale:50000

レイヤーの透明度の設定

opacity:0.5

初期表示の設定

center: [139.740286, 35.678601],
zoom: 15

レイヤの表示/非表示の制御

dojo/on モジュールを使用します。

on(vectorTileToggle, "change", function() {
    vectorTileLayer.visible = vectorTileToggle.checked;
});
on(mapImageToggle, "change", function() {
    mapImageLayer.visible = mapImageToggle.checked;
});
on(boundaryToggle, "change", function() {
    boundary.visible = boundaryToggle.checked;
});

レイヤー一覧ボタンの配置

当該ボタンを押すと layerToggle の表示/非表示が切り替わります。

function displayLayerList(){
    var toggle = document.getElementById("layerToggle");
    if(toggle.style.display=="block"){
      // 非表示
      toggle.style.display ="none";
    }else{
      // 表示
      toggle.style.display ="block";
    }
}      

<body>
    <ul id="menu">
      <li id="menu">
        <button id="button" type="button" onClick="displayLayerList()">レイヤー一覧</button>
      </li>
    </ul>
  <div id="viewDiv"></div>
  <div id="layerToggle">
    <input type="checkbox" id="vectorTileLayer" checked/>背景<br>
    <input type="checkbox" id="mapImageLayer" checked/>国土数値情報 災害情報<br>
    <input type="checkbox" id="boundary" checked />平成 27 年国勢調査 都道府県界<br>
  </div>
</body>

サンプルコード

全コードを以下に記載します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <title>レイヤ一覧表示</title>
  <link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
  <script src="https://js.arcgis.com/4.12/"></script>
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
    #layerToggle {
      display: none;
      top: 80px;
      right: 20px;
      position: absolute;
      z-index: 99;
      background-color: white;
      border-radius: 8px;
      padding: 10px;
      opacity: 0.75;
    }
    #menu{
      padding: 0;
      margin: 0;
	  height:42px; 
      background-color:#eeeeee;
      font-weight:bold;
    }
    #menu li {
      height:42px;
      margin-right: 2px;
      display: inline-block;
    }
    #button {
      left:0px;
      width:164px; 
      height:42px;
    }

  </style>
  <script>
    require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/VectorTileLayer",
        "esri/layers/FeatureLayer",
        "esri/layers/MapImageLayer",
        "dojo/on",
        "dojo/domReady!"
      ],
      function(
        Map, 
        MapView, 
        VectorTileLayer,
        FeatureLayer, 
        MapImageLayer,
        on
      ) {
        
        var map = new Map({
            basemap: "gray-vector"
        });

        var vectorTileLayer = new VectorTileLayer({
          url:
            "https://www.arcgis.com/sharing/rest/content/items/92c551c9f07b4147846aae273e822714/resources/styles/root.json",
            id:"vectorTile"
        });
        
        var mapImageLayer = new MapImageLayer({
            url: "https://content.esrij.com/arcgis/rest/services/Dosyasaigai/Dosyasaigai_Tile/MapServer",
            id:"mapImage"
        });

        var boundary = new FeatureLayer({
          url:"https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/JPN_Boundaries_ECM/FeatureServer",
          id:"boundary",
          opacity:0.5,
          minScale:1500000,
          maxScale:50000
        });
          
        map.add(vectorTileLayer);
        map.add(mapImageLayer);
        map.add(boundary);

        var view = new MapView({  
          container: "viewDiv",
          map: map,
          center: [139.740286, 35.678601],
          zoom: 15
        });

        var vectorTileToggle = document.getElementById("vectorTileLayer");
        var mapImageToggle = document.getElementById("mapImageLayer");
        var boundaryToggle = document.getElementById("boundary");

        on(vectorTileToggle, "change", function() {
          vectorTileLayer.visible = vectorTileToggle.checked;
        });
        on(mapImageToggle, "change", function() {
            mapImageLayer.visible = mapImageToggle.checked;
        });
        on(boundaryToggle, "change", function() {
          boundary.visible = boundaryToggle.checked;
        });
      });

      function displayLayerList(){
        var toggle = document.getElementById("layerToggle");
        if(toggle.style.display=="block"){
          // 非表示
          toggle.style.display ="none";
        }else{
          // 表示
          toggle.style.display ="block";
        }
      }      
  </script>
</head>
<body>
    <ul id="menu">
      <li id="menu">
        <button id="button" type="button" onClick="displayLayerList()">レイヤー一覧</button>
      </li>
    </ul>
  <div id="viewDiv"></div>
  <div id="layerToggle">
    <input type="checkbox" id="vectorTileLayer" checked/>背景<br>
    <input type="checkbox" id="mapImageLayer" checked/>国土数値情報 災害情報<br>
    <input type="checkbox" id="boundary" checked />平成 27 年国勢調査 都道府県界<br>
  </div>
</body>
</html>


少し動かしてみます。以下のようにスケールを変更すると「平成 27 年国勢調査 都道府県界」レイヤーが表示されます。

f:id:sanvarie:20191012122548p:plain

少し見づらいという場合は当該レイヤーを非表示にすれば大丈夫です。「国土数値情報 災害情報」レイヤーがはっきり見えるようになりました。かっこいいですね!

f:id:sanvarie:20191012122719p:plain

ソースは少し複雑そうに見えるのですが、実際は大したことはしていません。単純に地図を表示するだけでも大丈夫なのですが、今回のようにボタンを追加したりすると、そこから色々な処理を展開することができます。例えば、マップとの対話的な操作などでしょうか。次回はこのソースをベースにもう少し機能を追加してみようと思います。本日は以上です。