ベクトルタイル地図のウェブアプリを作るには（Mapbox GL JSやMapLibre GL JSのプラグインの実装）

# はじめに
これまでにベクトルタイルの生産、スタイル、ホスト等のことをこれまでに紹介していきましたが、今回はベクトルタイルの消費に関して書こうと思います。

具体的には、どうやってベクトルタイル地図のウェブ地図、あるいはウェブアプリを作るのか、使うライブラリとプラグインなどについて書きたいと思います。



# 地図ライブラリについて
まず、どんな地図ライブラリを使うか考える際の参考として、ここでは3つのライブラリを紹介します。

## Mapbox GL JS
Mapboxさんのライブラリです。ベクトルタイルの描画に最もよく使われているライブラリではないかとおもいます。クライアントサイドJavaScriptライブラリで、快適なウェブ地図を作成することができます。

現在のVersionは v.2.8.2です。2020年12月、ver1.x から ver.2.xに移行するときに、ライセンスの変更があったので利用するときにはライセンスをよく確認して使いましょう。（トークンはmapboxのホームページで登録するとgetできます。）
 
https://docs.mapbox.com/mapbox-gl-js/guides/

少し前のものですが、Mapbox GL JS ver1.xを使って作った簡単な地図はこんな感じです。
https://ubukawa.github.io/vt-test/maps/test-simple-mapbox.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/97f4ba9f-ac92-90e7-d701-5a62cbbc1177.png)


## MapLibre GL JS
Mapbox GL JS (ver.1.x) から派生した、オープンソースのJavaスクリプトライブラリです。Mapbox GL JSのver.1にあった機能を有しています。ベクトルタイルのスタイルなどはMapbox GL JSと同じものを使えることがほとんどです。最近は独自の機能なども増えてきたようです。

https://maplibre.org/projects/maplibre-gl-js/

少し前のものですが、MapLibreを使って作った簡単な地図はこんな感じです。（Mapbox GL JSとほとんど同じ。）
https://ubukawa.github.io/vt-test/maps/test-simple-maplibre.html#2/0/0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/b92c70e1-ec1f-d5c1-de4a-6fb21e6fb113.png)


## ArcGIS API for JavaScript
これも地図描画のためのJavaScript APIです。ESRIさんの製品を使うために使われます。私の職場ではArcGIS Onlineを使っていることもあり、このライブラリをつかってベクトルタイルの実験をしたことがあります。
この中でもMapbox/Maplibre仕様に準拠したJSONスタイル情報を読むことでベクトルタイルを表示できるようになります。

Esriサーバー以外から提供されているベクトルタイルを追加するためには、以下の技術情報が参考になります。
* [「地理院地図Vector」 (仮称) を ArcGIS で表示してみました（ESRIジャパンブログ, 2019）](https://community.esri.com/t5/arcgis-%E9%96%8B%E7%99%BA%E8%80%85%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3-documents/%E5%9C%B0%E7%90%86%E9%99%A2%E5%9C%B0%E5%9B%B3vector-%E4%BB%AE%E7%A7%B0-%E3%82%92-arcgis-%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F/ta-p/914680)
* [「地理院地図Vector」(仮称)をArcGIS で表示してみました - 第2弾（ESRIジャパンブログ, 2020）](https://community.esri.com/t5/arcgis-%E9%96%8B%E7%99%BA%E8%80%85%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3-documents/%E5%9C%B0%E7%90%86%E9%99%A2%E5%9C%B0%E5%9B%B3vector-%E4%BB%AE%E7%A7%B0-%E3%82%92arcgis-%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F-%E7%AC%AC2%E5%BC%BE/ta-p/906742)
* [「地理院地図Vector」(仮称)をArcGIS で表示してみました-第3弾（ESRIジャパンブログ, 2021）](https://community.esri.com/t5/arcgis-%E9%96%8B%E7%99%BA%E8%80%85%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3-documents/%E5%9C%B0%E7%90%86%E9%99%A2%E5%9C%B0%E5%9B%B3vector-%E4%BB%AE%E7%A7%B0-%E3%82%92arcgis-%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F-%E7%AC%AC3%E5%BC%BE/ta-p/1041816)

利用にあたっては、ArcGIS Develperへのサインアップが必要です。
https://developers.arcgis.com/javascript/latest/licensing/

また、ESRIさんの[TOR](https://www.esri.com/en-us/legal/terms/product-specific-scope-of-use)の中、64条で以下の記述があるので（2022年6月1日現在）、ArcGIS API for JavaScriptをESRI製品を使わない場合の地図ライブラリとして使うことはないと思います。

> 64. Value-Added Applications for web deployment must be used in conjunction with other Esri Products. Third-party technologies may also be used in conjunction with Value-Added Applications as long as the Value-Added Applications are always used in conjunction with other Esri Product(s).

少し前のものですが、ArcGIS REST API for JavaScript（4.16）を使って作った簡単な地図はこんな感じです。
https://ubukawa.github.io/vt-test/maps/test-simple-arc.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/c7d5e06e-d848-46e0-1be7-8f3582aa265f.png)


## 他のライブラリについて
私は主に上記のライブラリでベクトルタイルを扱っているので、Leafletや他のライブラリでのベクトルタイルの扱いはこの記事では書きません。しかし他にもベクトルタイルを扱えるライブラリがあることをここにメモしておきます。

# プラグインを使ったウェブ地図構築について（Mapbox GL JS　と　MapLibre GL JS）
## ウェブ地図を拡張するためのプラグイン（Mapbox GL JS　と　MapLibre GL JS）
私自身はベクトルタイルの地図を作るときに、Mapbox GL JS や MapLibre GL JSでウェブ地図を使うことが多いです。これらのライブラリで地図を作った後、既存のプラグインを追加することでウェブ地図機能を充実させることができ、使い道が広がるアプリになる可能性があります。（下の図はいくつかプラグインをつけた例です。）
![2022-05-02-plugin-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/ff713c48-91b6-4166-573d-327710deff73.png)



Mapbox GL JS と MapLibre GL JSの両ライブラリのページから、それぞれのプラグインが紹介されています。

* プラグイン一覧
    * Mapbox GL JS のプラグイン https://docs.mapbox.com/mapbox-gl-js/plugins/
    * MapLibre GL JS のプラグイン https://maplibre.org/maplibre-gl-js-docs/plugins/

以下に、よく使いそうなプラグインをいくつかピックアップして紹介します。

|機能|名前|MapBox  |MapLibre  |備考 |
|---|---|---|---|---|
|スタイルの切り替え  |StyleSwitcherControl  |el/style-switcher, watergis/style-switcher  |N/A (ver1.14以前は可)  |MapLibreのサポートについては[issue#14](https://github.com/el/style-switcher/issues/14)にて話されている。 |
|ポップアップで属性表示  |PopupControl  |watergis/mapbox-gl-popup| N/A |WaterGISさんオリジナル。プラグインを使わないときはpopup-on-clickを使って実装しないといけない。 |
|3Dと2Dの切り替えボタン |PitchToggleControl  |tobinbradley/mapbox-gl-pitch-toggle-control, watergis/mapbox-gl-pitch-toggle-control| N/A |右ドラッグでもできるがボタンでも角度を切り替えるもの。WaterGISさんはTypeScript。 |
|範囲の切り替え（ジャンプ）  |AreaSwitcherControl  |watergis/mapbox-gl-area-switcher |N/A |WaterGISさんオリジナル |
|凡例のコントロール  |LegendControl  |watergis/mapbox-gl-legend |watergis/maplibre-gl-legend |WaterGISさんがmapparatus/legend-symbolから開発した。地図の都合でレイヤ数が多い場合は工夫が必要だと思う。 |
|地図出力 |ExportControl  |watergis/mapbox-gl-export, geolonia/mbgl-export-control  | watergis/maplibre-gl-export |Mapbox 用には、WaterGISさんがmpetroff/print-mapsから開発したものと、Geoloniaさんが開発したものがある。 |
|標高値の表示など  |ElevationControl  | watergis/mapbox-gl-elevation|N/A  |WaterGISさんオリジナル。開発中 |
|GeoCoder  |Geocoder |mapbox-gl-geocoder |maplibre-gl-geocoder | MapboxにとってはPluginではありません。|

このほか、2つの地図を比べるcompareなども便利なプラグインです。

## プラグインの実装方法
### 基本的な実装
実装の仕方について簡単にまとめます。
例として、2つのMapLibreで作った地図（衛星画像）の比較をするプラグイン(maplibre-compare)を使ったページの例をみてみます。
* ページ　https://ubukawa.github.io/sentinel2-Beijin20220102/maps/map2.html#13.88/40.04091/116.51393
* ソース　https://github.com/ubukawa/sentinel2-Beijin20220102/blob/main/maps/map2.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/b08a1dbb-2c46-61b7-5df7-123fdd8eca9d.png)

#### プラグインの読み込み
ウェブ地図を作るときhtmlファイルでmapboxやmaplibreのライブラリを以下のように読んでいると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/28c181e8-477a-bf4c-53f0-e5812df616fc.png)

このファイルの中に、プラグインのライブラリを追加します。JavaScriptファイルとCSSを読むことが多いです（下の例ではmaplibre-gl-compareを読んでいます）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/36fc47bc-9a37-37c7-e142-341daf9b8312.png)

#### プラグインの利用
そして、そのプラグインを使っていけばOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/6fea3e50-c611-1ca9-ffa0-15ca6e614194.png)

### プラグイン実装の際の工夫
このようにしていきますが、たくさんのプラグインを使う場合には、読み込むJSファイル（モジュール）が多くなりすぎることがあります。
その場合には、[webpack](https://webpack.js.org/)などのモジュールバンドラを使ってモジュールをまとめる（バンドル化）するという工夫が有効だと思います。

@JinIgarashi さんが作成された[watergis/mapboxgljs-boilerplate](https://github.com/watergis/mapboxgljs-boilerplate)にはそうした工夫が入っていますし、mapboxgljs-boilerplate では config.jsで指定したコンフィグ情報も一緒にバンドルを作れるようになっています（そうすると地図のhtmlファイルからはbundle.jsだけを参照すればよい）。勉強になりますね。


# おまけ：　地理院地図Vectorを使ったウェブ地図構築について
ベクトルタイルのウェブ地図アプリを作るにあたって、オープンソースである地理院地図Vector（仮称）を使ってみたいと考えたことがあります。

実際に、ラスタタイルベースの地理院地図を参考にして[全国Q地図](https://info.qchizu.xyz/qchizu/)さんのようなアプリも作られていますし、ベクトルタイルでもできるのではないかと考えた次第です。

>全国Q地図は、githubで国土地理院が公開している地理院地図のソースコードをもとに公開しています。　（https://info.qchizu.xyz/qchizu/improve/ より）

地理院地図Vector（仮称）のレポジトリは https://github.com/gsi-cyberjapan/gsimaps-vector-experiment にあります。ウェブサーバーでホストすればウェブ地図を見ることができますので、半年くらい前に、自分のベクトルタイルを使ってこんな感じのテストをしてみました。
![2022-05-02-gsimap-v.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/6ce9a6dc-6196-ca7c-15c0-05d282ed891e.png)

地理院地図Vector（仮称）の中身をカスタマイズしていくためには、例えば以下のようなことが必要になると思います。

* htdocsのindex.html を編集する
* htdocs/sprite に必要な地図記号を入れる
* htdocs/image を適宜差し替える
* htdocs/dataの中のスタイルファイル（json）を編集する。自分のスタイルにする。
    * **ただし、ここで使っているスタイルJSONは地理院地図独自の拡張がされており、mapboxやmaplibreのスタイル仕様に即しているわけではない。**　構造が違うので、jsonファイルをよく見て対応を考える必要がある。（地理院地図 Vector（仮称）地図デザインファイル仕様 https://maps.gsi.go.jp/help/pdf/vector/stylespec.pdf ）
    * 簡単にいうと、groupは無視して、一つのgroupにしてしまい、listの中に、type=itemの要素を作って、その中のlistにtype=layerの要素を作って、その中はmapboxやmaplibreのlayer要素と同じように書けばいい。
    ![2022-05-02-gsimap-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/74344dd7-1f7f-2821-e087-0be53d58435c.png)
* htdocs/data/config.js の中でおすすめ地図のサムネイル、タイトル、url（スタイルjsonの場所）を指定する。
* htdocs/js/gsimaps-bvtile.js　のメニューを英語にする
* htdocs/js/src/data/vectortiledata.js　を編集する　（ここにpbfタイルの指定場所があります）
* htdocs/js/src/data/vectortilestyle.js　を編集する
などなど

ということで思った以上に大変で、なかなかうまくカスタマイズができなかったのでそれ以上追求していません。
特に、スタイル仕様の違いのところは他のベクトルタイル地図との間での大きな壁なので、私の力量では厳しいものがありました。

# まとめ
この記事では、ベクトルタイルの消費の分野のうち、ウェブ地図アプリをどうやって作るかというところについて私の経験をまとめました。

# 謝辞
Mapbox GL JS (ver1.x) やMapLibre GLJSのプラグインに関しては、@JinIgarashi さんの作ったレポジトリを勉強させていただいています。ここに感謝いたします。

# References

* ライブラリ
    * Mapbox GL JS　https://docs.mapbox.com/mapbox-gl-js/guides/
    * MapLibre GL JS　https://maplibre.org/projects/maplibre-gl-js/
    * ArcGIS API for JavaScript https://developers.arcgis.com/javascript/latest/
* プラグイン関係
    * el/style-switcher　https://github.com/el/style-switcher
    * watergis/style-switcher　https://github.com/watergis/mapbox-gl-area-switcher
    * watergis/mapbox-gl-popup https://github.com/watergis/mapbox-gl-popup
    * tobinbradley/mapbox-gl-pitch-toggle-control https://github.com/tobinbradley/mapbox-gl-pitch-toggle-control
    * watergis/mapbox-gl-pitch-toggle-control https://github.com/watergis/mapbox-gl-pitch-toggle-control
    * watergis/mapbox-gl-area-switcher https://github.com/watergis/mapbox-gl-area-switcher
    * watergis/mapbox-gl-legend https://github.com/watergis/mapbox-gl-legend
    * watergis/maplibre-gl-legend https://github.com/watergis/maplibre-gl-legend
    * watergis/mapbox-gl-export https://github.com/watergis/mapbox-gl-export
    * geolonia/mbgl-export-control https://github.com/geolonia/mbgl-export-control
    * watergis/maplibre-gl-export https://github.com/watergis/maplibre-gl-export
    * watergis/mapbox-gl-elevation https://github.com/watergis/mapbox-gl-elevation
    * mapbox-gl-geocorder https://github.com/mapbox/mapbox-gl-geocoder
* Repository
    * 地理院地図Vector（仮称）提供実験　https://github.com/gsi-cyberjapan/gsimaps-vector-experiment
    * mapboxgljs-boilerplate　https://github.com/watergis/mapboxgljs-boilerplate
    * maplibre-compareの例（私が作った衛星画像比較）　https://github.com/ubukawa/sentinel2-Beijin20220102/
    * 地理院地図Vector（仮称）を試したレポジトリ（不完全）　https://github.com/ubukawa/test-map
* Other
    * Webpack https://webpack.js.org/
    * Q地図 https://info.qchizu.xyz/qchizu/
    * 地理院地図 Vector（仮称）地図デザインファイル仕様 https://maps.gsi.go.jp/help/pdf/vector/stylespec.pdf