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

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

ArcGIS API for JavaScript のウィジェットを使ってみよう

さて、本日は ArcGIS API for JavaScript について書いてみようと思います。

ArcGIS API for JavaScript とは

ArcGIS API for JavaScript はWeb ブラウザー向けのアプリケーションや Web サイトに GIS(地図)機能を組み込むための API です。これを使用することにより以下のようなことが実現可能になります。

  • 地図表示・操作
  • デバイス連携(GPS・カメラ等)
  • 図形・属性情報編集
  • 距離・面積計測
  • 空間・属性検索
  • 各種解析機能
  • リアルタイム データ表示
  • 3D(※ バージョン 4.0 以降)

なぜ ArcGIS API for JavaScript を取り上げるのか

GIS は昔と違いどんどん Web 化の方向に進んでいます。なので、本ブログでも Web GIS についてもっと取り上げていこうと思い、ArcGIS API for JavaScript をチョイスしてみました。ただ、私も初心者に毛が生えたようなものなので、勉強しながら API にまつわる色々なことを紹介していければと思います。

ArcGIS API for JavaScript は無償で利用可能

開発リソースは ArcGIS for Developers にて開発者アカウントを作成すれば、一部の機能を除き無償で利用可能です。素晴らしいですね!

今回やってみること

まずは簡単なところから始めてみようと思います。色々なことができる API なのですが、私の一押しはウィジェットです。Web アプリなどを開発する際、一から部品を作るのは時間がかかりますし、不具合が発生するリスクもあるかと思います。

ArcGIS API for JavaScript で使用できるウィジェットを使えば、誰でも簡単に便利な部品を使うことができます。今回はその中のほんの一部になりますが、以下を紹介しようと思います。

  • BasemapGallery widget

    • 使用できるベースマップの一覧を表示するウィジェットです。ウィジェット内に表示されているベースマップをクリックすると、マップのベースマップが切り替わります。
  • Locate button

    • 現在位置に移動できるボタンです。モバイルで使用する際に非常に便利な機能ですね。

これらの機能ですが、自分で一から作ろうとすると非常に大変だと思いますが、ArcGIS API for JavaScript を使えば、簡単に実装することができます。

実行環境

ArcGIS API for JavaScript 4.12
Chrome

サンプル

BasemapGallery widget と Locate button を使用したサンプルです。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1, maximum-scale=1,user-scalable=no"
    />
    <title>sample of Locate button and BasemapGallery widget - 4.12</title>
    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.12/esri/themes/light/main.css"
    />
    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>
    <script src="https://js.arcgis.com/4.12/"></script>
    <script>
      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/widgets/Locate",
        "esri/widgets/BasemapGallery"
      ], function(Map, MapView, Locate, BasemapGallery) {
        var map = new Map({
          basemap: "streets"
        });

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

        var locateBtn = new Locate({
          view: view
        });
        
        var basemapGallery = new BasemapGallery({
          view: view
        });

        // Add the locate widget to the top left corner of the view
        view.ui.add(locateBtn, {
          position: "top-left"
        });
        
        view.ui.add(basemapGallery, {
          position: "top-right"
        });
      });
    </script>
  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>

ポイント

  • <script src="https://js.arcgis.com/4.12/"></script> で API の読み込みをしています。
  • その下の <script>~</script> でマップの表示とウィジェットの読み込みをしています。

これを html として保存して開いてみると、このような感じになります。

f:id:sanvarie:20190930160707p:plain

場所は center: [139.740286, 35.678601] で設定しています。今回は永田町を中心点にしてみました。

マイナスボタンの下にあるのが Locate button で右側にあるのが BasemapGallery widget です。

Locate button を押すと、以下のように現在の場所に移動します。

f:id:sanvarie:20190930161050p:plain

BasemapGallery widget で衛星画像を選択するとこのようにベースマップが切り替わります。素晴らしいですね。

f:id:sanvarie:20190930161355p:plain

このようにウィジェットを使用すると、便利な機能を簡単に実装することができます。今後も他のウィジェットや別の機能などを色々紹介していこうと思うので、興味がある方はぜひ読んでみてください。

参考サイト

ArcGIS API for JavaScript を使用して開発をするために必要となるサンプルコードなどが色々ありますので、ぜひ活用してみてください。

https://www.esrij.com/products/arcgis-api-for-javascript/documents/

Python でリストを CSV 出力する方法

さて、今回は Python でリストを CSV 出力する方法を紹介しようと思います。単純に一次元のリストだけではなく、多次元のリストにも対応したソースを紹介しますので、興味のある方はぜひ読んでみてください。

環境

Windows 10
Python 3.6.5

出力するデータ

すごく単純なデータですが、[1,2,3]と [[1,2,3],[4,5,6],[7,8,9]]というデータを CSV 出力してみようと思います。

使用するライブラリ

csv というPython の標準ライブラリを使用します。

サンプル

一次元と多次元のリストを CSV 出力するサンプルです。

# -*- coding: utf-8 -*-
import csv

def export_list_csv(export_list, csv_dir):

    with open(csv_dir, "w") as f:
        writer = csv.writer(f, lineterminator='\n')

        if isinstance(export_list[0], list): #多次元の場合
            writer.writerows(export_list)

        else:
            writer.writerow(export_list)

def make_list():
    one_dimensional_list = [1,2,3]
    two_dimensional_list = [[1,2,3],[4,5,6],[7,8,9]]

    export_list_csv(one_dimensional_list, r"D:\data\one_dimensional_list.csv")
    export_list_csv(two_dimensional_list, r"D:\data\one_dimensional_list.csv")

if __name__ == '__main__':
    make_list()
  • ポイント
    if isinstance(export_list[0], list): で多次元かどうかを判別しています。意外と便利な isinstance() ですね。

結果

EXCEL で出力した CSV を開いてみました。想定通りの結果が得られました。

f:id:sanvarie:20190928121345p:plain

f:id:sanvarie:20190928121401p:plain

今後は こういった Python の小ネタ集も作っていきたいと思いますので、ぜひ読んでみてください。

ArcGIS Pro で ポイントをアノテーションに変換する方法

さて、本日は ArcGIS Pro で ポイントをアノテーションに変換する方法について紹介したいと思います。

使用するデータ

位置参照情報のデータを使用したいと思います。位置参照情報については以下エントリーでも紹介していますので、興味のある方はぜひ読んでみてください。

www.gis-py.com

www.gis-py.com

データの詳細

今回は大字・町丁目レベルの横須賀市のデータを使用したいと思います。形式は CSV になっています。

f:id:sanvarie:20190927201811p:plain

アノテーション化する属性

「大字町丁目名」という属性をアノテーション化します。

手順

1.「XYテーブル→ポイント」ジオプロセシングツールで CSV をポイントにします。

「XYテーブル→ポイント」で以下のようにパラメーターを設定して「実行」ボタンをクリックしてください。
f:id:sanvarie:20190927202325p:plain

CSV のデータがポイントとして登録されました。 f:id:sanvarie:20190927202354p:plain

2.「大字町丁目名」をラベルとして設定します。

コンテンツウインドウで登録されたポイントレイヤーを右クリックし、「ラベル プロパティ」をクリックしてください。
f:id:sanvarie:20190927202608p:plain

ラベルクラス ウインドウが表示されるので、条件式に「$feature.大字町丁目名」と入力して「適用」ボタンをクリックしてください。
f:id:sanvarie:20190927202702p:plain

再度、コンテンツウインドウで登録されたポイントレイヤーを右クリックし、「ラベル」 をクリックしてください。
f:id:sanvarie:20190927202504p:plain

「大字町丁目名」がラベルとして表示されました。
f:id:sanvarie:20190927203055p:plain

3.「ラベルをアノテーションに変換」ジオプロセシングツールでラベルをアノテーションに変換します。

出力先を入力し、必要であればその他の設定を行い、「実行」ボタンをクリックしてください。
f:id:sanvarie:20190927203831p:plain

「大字町丁目名」ラベルがアノテーションに変換されました。
f:id:sanvarie:20190927203951p:plain

すごく簡単にポイントをアノテーションに変換することができました。文字表記はラベルで十分という方もいらっしゃるかと思いますが、GIS を使う場合、アノテーションを使用するケースは少なくないかと思います。緯度経度と属性さえあれば、このように簡単に CSV などのデータをアノテーション化できますので、ぜひ試してみてください。本日は以上です。

ArcGIS Pro で解析ツールギャラリーにお気に入りのジオプロセシングツールを登録しよう

さて、本日も ArcGIS Pro について書いてみようと思います。皆さんは ArcGIS Pro を使っていますか?ArcMap やほかのGIS デスクトップアプリで十分という場合もあるかもしれませんが、ArcGIS Pro を使えば、作業をより効率的に行うことができます。また、ArcGIS Pro はかゆい所に手が届く機能を数多く搭載しているので、まだ使ったことがないという方はぜひ使ってみてください。

ArcGIS Pro について、本ブログで色々紹介していますので、興味がある方はぜひ以下のエントリーも読んでみてください。
www.gis-py.com

www.gis-py.com

www.gis-py.com

ジオプロセシングツールとは

ArcGIS ユーザーの方はご存知かと思いますが、ESRIジャパンさんのサイトに詳しく載っていますので、そちらをご参照ください。

www.esrij.com

ジオプロセシングツールをもっと効率的に使うには

特定のジオプロセシングツールを毎日のように使用する場合、毎回、対象のジオプロセシングツールを検索して実行するのは少し面倒だと思います。そこで解析ツールギャラリーですね。解析ツールギャラリーにお気に入りのジオプロセシングツールを登録することができますので、ジオプロセシングツールを毎回検索するという面倒な作業を省くことができます。

解析ツールギャラリーとは

「解析タブ」にあります。以下赤枠の部分のことです。

f:id:sanvarie:20190927193625p:plain

解析ツールギャラリーにジオプロセシングツールを登録する方法

赤枠のところをクリックすると
f:id:sanvarie:20190927193709p:plain

このように展開するので、「カスタマイズ」をクリックします。
f:id:sanvarie:20190927193819p:plain

以下画面が起動します。「+」ボタンをクリックします。
f:id:sanvarie:20190927193945p:plain

グループ名を入力し、「+」ボタンをクリックします。
f:id:sanvarie:20190927194136p:plain

登録したいジオプロセシングツールを検索し、クリックします。
f:id:sanvarie:20190927194230p:plain

登録し終えたら最後にOKをクリックします。
f:id:sanvarie:20190927194344p:plain

解析ツールギャラリーに登録したジオプロセシングツールが表示されました。
f:id:sanvarie:20190927194506p:plain

あっさりできましたね。このように ArcGIS Pro には作業を効率化するための便利な機能がたくさん搭載されています。今後も少しずつになってしまうと思いますが、便利機能を紹介していきますので、ぜひ次回も読んでいただければと思います。

ArcGIS Pro で編集の自動保存をする方法

さて、本日は ArcGIS Pro で編集の自動保存をする方法を紹介します。以下のエントリーで ArcMap と ArcGIS Pro の違いを紹介したのですが、大きな違いのみを紹介しました。今回を含めてこれからはもう少し具体的に ArcGIS Pro になって追加された機能、進化した機能などを紹介しようと思います。

www.gis-py.com

編集の自動保存

ArcMap では「編集の開始」→「編集の保存」というようなステップを踏む必要がありましたが、ArcGIS Pro では「編集の開始」をする必要がなくなりました。その上、「自動保存」の設定をオンにすれば、「編集の保存」をしなくても、編集した内容が保存されます。編集中に ArcMap が落ちて涙をのんだという方もいるかと思いますが、そういった心配をする必要もなくなりました。

手順

1. ArcGIS Pro 起動後 > 「設定」を押下

f:id:sanvarie:20190907111423p:plain

2. 「オプション」を押下

f:id:sanvarie:20190907111607p:plain

3. 「編集」 > 「編集の保存」をチェックして、「OK」を押下

f:id:sanvarie:20190907111747p:plain


すごく簡単に設定できました。一日中編集をするような方にとっては痒いところに手が届く機能ではないでしょうか。興味のある方はぜひ使ってみてください。また、ちょくちょく ArcGIS Pro の小ネタについて紹介できればと思います。本日は以上です。

Node.js で WEB サーバーを簡単に構築する方法

さて、本日は Node.js で WEB サーバーを構築してみようと思います。あまりブログの趣旨とは関係ないところだとは思うのですが、実は今年のどこかで ArcGIS API for JavaScript の紹介と実際に当該 API を使用した WEBサイトの構築を考えているので、その前準備と勉強のためというのが本エントリーの主な理由です。

Node.js とは

もう皆さんご存知かと思いますが、Node.js はサーバーサイド Javascript の実行環境ですね。以下サイトに詳細が書いてあるので、興味がある方は是非読んでみてください。

qiita.com

実行環境

Windows 10

Node.js のインストール

以下サイトでインストーラーをダウンロードして、インストールをしてください。 nodejs.org

インストールが完了したら以下のコマンドで Node.js がインストールされていることとバージョンが確認できます。

node --version

f:id:sanvarie:20190728133640p:plain

以下のコマンドで npm (node package manager) がインストールされていることとバージョンが確認できます。

npm --version

f:id:sanvarie:20190728133446p:plain

WEB サーバーを構築

Express を使って WEB サーバーを構築してみようと思います。

Express とは

Express は Node.js での開発をスピードアップするためのフレームワークです。

Express をインストール

  • 新規プロジェクト用に空のディレクトリ作成
  • そのディレクトリで以下コマンドを実行してプロジェクトを初期化。プロンプトでいくつかの質問に回答し package.json ファイルを生成。
npm init
  • 以下コマンドで Express をインストール
npm install express --save

サンプルコード

アクセスするとHello World!とブラウザに表示する簡単なサーバーサイド処理のサンプルです。

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello World!');!');
});
app.listen(3000, function () {
});

Express の実行

以下コマンドで Express を実行することができます(index.js は今回使用するファイル名なので、異なる名前のファイルを使用する場合はそれに合わせてコマンドを変えてください)。

node index.js

f:id:sanvarie:20190728140448p:plain

準備はすべて整いました。後はhttp://localhost:3000/にアクセスするだけですね。

f:id:sanvarie:20190728140732p:plain

ばっちりですね!

簡単に WEB サーバーの構築ができました。実際に WEB サイトを構築するにはこれでは不十分かと思いますが、このように簡単に始められるのはとても助かりますね。