この記事は、週末に書いた記事Vector tile styling with unvt/charitesの日本語版です。すべてを正確に訳したわけではないですが、日本語でもメモしておきます。
はじめに
unvt/charites は簡単、直感的、効率的なコマンドラインツールで、ベクトルタイル地図を作るため、Mapbox や MapLibreのスタイル仕様に適合したスタイルをYAMLファイルで作成することができます。
YAMLファイルは読みやすく、またcharitesのライブプレビュー機能はスタイル編集を助けてくれます。
この記事では、Windows PCでcharitesをインストールする方法と、その使い方を紹介します。unvt/charitesと、さらにはスタイル仕様をよく理解できるようにいくつかの練習があります。簡単なものもあるかもしれませんが、unvt/charitesを使ってベクトルタイルのスタイルを作成することに興味があればご覧いただけれるとうれしいです。
この作業の大半は国連オープンGISイニチアチブのドメイン作業部会7に対する私の活動として行ったものに基づいています。
本稿はもともとは同僚の M.T., O.M.S., P.F.のために書いたものです。
私の実験環境
- Windows 10
- git
- nodejs version 18.12.1
- npm version 8.19.2
- Windows PowerShell
Exercise 1. unvt/charites のインストール
1-1. nodejs と npm のバージョン確認(又はインストールされているか確認)
nodejs インストールされているか確認しましょう。もしされていない場合は、nodejs からダウンロードしましょう。バージョン14以降を使うことが奨励されます。特に12.20.20より古いバージョンだとcharitesのインストールは失敗すると思います。
Windows PowerShell を開いて、以下のコマンドを実行するとバージョンを確認できます。
node --version
npm --version
1-2. npm パッケージ(@unvt/charites)のインストール
nodejsとnpmがあることを確認したら、以下のコマンドを実行し unvt/charites の npm パッケージをインストールします。うまくインストールするとcharites --versionでcharitesのバージョンを確認できます。
npm install -g @unvt/charites
charites --version
charites --help
これでunvt/charitesを使えます。おめでとうございます!
Exercise 2. スタイルの編集
charites でベクトルタイルのスタイルを編集します。
2-1. 新しいスタイルをはじめから作る
もしも既存のスタイルJSONを持っていれば、charitesでインポートするとよいので簡単です。しかし、もし初めからスタイルを作るのであれば、私が準備したテンプレートを使ってみます。私のレポジトリからテンプレートをコピーしてきます。以下のようなコマンドで出来ます。
git clone https://github.com/ubukawa/charites-init
クローンした "charites-init" のなかにはstyle.ymlが入っています。layersフォルダもありますね。
2-2. style.yml を編集して、sources, sprites, glyphs を指定する。
何もしていないとき、style.yml は以下のような感じですが、これを編集していきます。
最初にstyle.ymlをなんでもよいのでテキストエディタで開きます。MicroSoft Visual Studio Codeで編集するのも便利でよいと思います。コメントタグ(#)を削除して必要な事項を以下の方針で記入していきます:
- sprite
- sprite は、地図記号や塗りのパターンを与えるための画像ファイルとJSONファイルです。
- 今回の練習では、 "https://ubukawa.github.io/clearmap-style2/sprite_un/sprite_S" を使います。
- glyphs
- glyphs にはpbf形式のテキストフォントの場所を指定します。
- 今回の練習では "https://ubukawa.github.io/clearmap-style2/font/{fontstack}/{range}.pbf" を使います。
- sources
- ここにデータソースを指定することができます。ベクトルタイル、ラスタタイル、WMS、raster-demなど指定できます。今回は以下のyamlファイルにあるように3つのベクトルタイルソースを指定します。YAMLファイルを確認してみてください。
version: 8
sprite: https://ubukawa.github.io/clearmap-style2/sprite_un/sprite_S
glyphs: https://ubukawa.github.io/clearmap-style2/font/{fontstack}/{range}.pbf
sources:
ne: #change the name if needed
type: vector
attribution: NaturalEarth #add if needed
minzoom: 0 #add if needed
maxzoom: 5 #add if needed
tiles:
- https://ubukawa.github.io/graticules-vt/zxy/{z}/{x}/{y}.pbf
carto: #change the name if needed
type: vector
attribution: Cartotile - Test data #add if needed
minzoom: 0 #add if needed
maxzoom: 2 #add if needed
tiles:
- https://ubukawa.github.io/cartotile/tile/{z}/{x}/{y}.pbf
cme: #change the name if needed
type: vector
attribution: UN_CLEARMAP_VT(powered by esri)
minzoom: 0 #add if needed
maxzoom: 5 #add if needed
tiles:
- https://pro-ags2.dfs.un.org/arcgis/rest/services/Hosted/Clearmap_Webplain/VectorTileServer/tile/{z}/{y}/{x}.pbf
layers:
- !!inc/file layers/background.yml
# add any layer if needed
2-3. charites ライブプレビュー開始
これでstyle.ymlを編集しましたので、ローカルホストでcharitesのライブプレビューを立ち上げることが出来ます。ただし、現時点ではバックグラウンドのレイヤしかありませんので(コピーしてきたパッケージに含まれていた)、地図のレイヤは何も見えないはずです。
cd charites-init
charites serve style.yml #(Ctrl + c to stop)
ライブプレビューは http://localhost:8080 から見られます。
2-4. background color の変更の練習 (色の表現にも慣れてみましょう)
試しに layers/background.yml を編集して、 backgound-color を変えてみましょう。テキストエディタで編集できます。 色の指定は index color (e.g. '#D6EBF5')でも, rgb color (e.g. rgb(0,0,100))でも, rgba color (e.g. rgba(10,0,100,0.7))でもできます。また、 "red", "green", "blue"などの表現でも大丈夫です (参照: https://maplibre.org/maplibre-gl-js-docs/style-spec/types/#color )。 ただし、QGIS plugin や Esrc's ArcGIS API for Javascriptなどでは、それぞれ使える色の表現が違う可能性があるので気を付けましょう。
2-5. レイヤ(layer)を足してみよう: グリッドライン(緯度経度の線)
charites ライブプレビューを実行したまま作業を続けます。まず、ラインのレイヤを足してみます。NaturalEarthの30度の経緯度線を足してみます。style.yml中ではneとしたソースです。編集を簡単にするため、charites-init/layers/layer_samplesの中に私が準備しておいたサンプルのyamlファイルを使います。"ls-line-sample.yml" を "ls-grid30.yml" としてコピーして、それを編集します。
charites ライブプレビューが走ったままなので、新しいコマンドラインを立ち上げないといけないかもしれません。
cd charites-init/layers
cp layer_samples/ls-line-sample.yml ls-grid30.yml
上のコマンドのようにコピーしてきたら、 "ls-grid30.yml" を以下のように編集します。
テンプレートにはコメントタグがいくつかありますが、内容は以下のYAMLファイルのようにシンプルです。
id: ls-grid30
minzoom: 0
maxzoom: 5
paint:
line-color: '#999999'
line-width: 0.7
source: ne
source-layer: grid30
type: line
しかし、ここまで作業しても、ライププレビューには何も変化が見られないでしょう。この後に、style.ymlを編集してlayersのリストに一行追加する必要があります。 style.ymlの中で参照されているlayersの一覧の中に、一行以下のように追加してください。リストの中で下に来るレイヤほどウェブ地図の中では上に来ることに注意しましょう。
charites はファイルの更新を見つけて、変更を自動でライブプレビューに反映してくれます。
うまくいくと以下のような画面になります。おっと、私が作ったグリッドのベクトルタイルはズームレベルが1~5だったようです。ですので、レイヤのスタイルで最大最小ズームを0ー5にしても、ウェブ地図ではズームレベル 0 から 1 未満で線が出てこないことを確認してください。
この失敗から、ソースとなるベクトルタイルの構造をよく理解しておくことの重要性がわかります。スタイルで最大最小ズームを定義しなくても、ソースの最大最小ズームレベルでコントロールすることができます。(また、オーバーズーミングがどのように効いてくるかということも、ここでは説明しませんが理解しておくとよいと思います。)
2-6. レイヤを足してみよう: ポリゴン(Fill)を足す
次に、陸地のポリゴンを足してみます。 Esri's Feature Service で次のところから提供されているポリゴンです: https://geoservices.un.org/arcgis/rest/services/Hosted/UN_Geodata_Stylized/FeatureServer/3?f=pjson .
2022年12月上旬にこのURLにアクセスして、データをベクトルタイルに変換しておいたものがあります。(方法は こちら ).
同じように、テンプレートの "pg-fill-sample.yml" を "pg-landmass.yml" としてコピーして編集します。
cp layer_samples/pg-fill-sample.yml pg-landmass.yml
id: pg-landmass
minzoom: 0
maxzoom: 5
paint:
fill-color: rgb(237,237,237)
source: carto
source-layer: bnda
type: fill
そして、style.yml にレイヤを追加するのも忘れないようにしましょう。backgroundより上ですが、グリッドラインよりは下にします。
こうすると、以下の図のような地図を見られると思います。以下のスクリーンショットを取った時の私のcharitesのバージョンは古かったのですが、もしcharitesのバージョンが0.3.0であれば左下にレジェンドのコントロールなどもあると思います。なお、追加した陸地ポリゴンはデザイン地図の用途につかっていたもので詳細地図用途ではないので座標値などはあまり正確ではありません。
2-7. レイヤを足してみよう: もう一つのラインレイヤを "filter"を使って加える
次に、もう一つのラインを足してみます。ここでは、レイヤに対して"filter"を使ってみます。ライン用のテンプレートを"ls-coastline.yml"としてコピーして、以下のように編集します。style.ymlにレイヤを足すことも忘れないようにしましょう。
filter:
- '=='
- - get
- bdytyp
- 0
id: ls-coastline
minzoom: 0
maxzoom: 5
paint:
line-color: '#0000FF'
line-width: 1
source: carto
source-layer: bndl
type: line
ここでは、フィルターを使って、bdytyp が 0 のものだけを表示するようにしています。例えば、0を1に変えてみて実験してみてください。
filterの使い方についてはいろいろな方法があります。もし興味があれば、私の別の記事(こちら)もご覧ください。
また、使う地図ライブラリによって、フィルタの表現を選ぶ必要もあると思いますので注意しましょう。
- 我々が今回使ったフィルタ (MapLibre/MapBoxで奨励されている): ["==",["get","bdytyp"],0]
- ArcGIS Online でよく使われているフィルタ(例): ["==","bdytyp",0]
2-8. レイヤを足してみよう: symbolをたす (filter と matchを使う)
最後にシンボルのレイヤも試してみます。ここでも filter を使いますし、今度は match という表現を使って、データの属性に応じた地図記号アイコンを割り振ります。
テンプレート(pt-symbol-sample.yml) を "pt-city.yml" としてコピーします。そして以下のように編集します。編集が終わればstyle.ymlにレイヤを追加します。グリッドラインと海岸線ラインの間に入れましょう。
filter:
- match
- - get
- _symbol
- - 0
- 1 #Alternative
- 2 #Territorial
- true
- false
id: pt-city
minzoom: 4
maxzoom: 5
layout:
icon-allow-overlap: true
icon-image:
- match
- - get
- _symbol
- 1
- PPL_Alternative
- 2
- PPL_Territorial
- PPL_National # for _symbol==0
icon-size: 1
text-allow-overlap: true
text-optional: true
text-field: '{_symbol}' #or [get, text_field] would be good.
text-font:
- Open Sans Regular #text font should be from glyphs
text-size: 10
text-anchor: bottom
text-offset:
- 1
- 1
#text-letter-spacing: 0.1
#text-max-width: 50
paint:
text-color: '#000000'
text-halo-color: '#FFFFFF'
text-halo-width: 0.8
source: cme
source-layer: Populated Places_SYMBOLS #polygon or line can be also used for labelling
type: symbol
少しだけ上のYAML (pt-city.yml)について説明します:
- フィルターが使われていますが、"_symbol" が [0, 1, 2] のいずれかであるものを選んでいます。"in"という論理演算子を使った表現にすることも可能ですが、今回は"match"を使っています。
- icon-imageにかんして、"match"表現を使うことで、"_symbol"属性に応じてアイコンを変えています。この"match"表現はMapLibre GL JS や Mapbox GJ JS でうまく働きますが、ArcGIS API for JavaScript や QGIS plugin では対応していない可能性があります (最新バージョンでは確認していません。)
- text-field では単純に"_symbol" を表示するようにしています。これはソースのベクトルタイルでシンボル用のベクトルタイルレイヤとラベル用のベクトルタイルが分かれていたためです。一つのベクトルタイルレイヤであれば、アイコンとラベルを一つのスタイルレイヤで表現することができます。
symbol レイヤについて、今回はポイントのベクトルタイルを使いましたが、ラインやポリゴンのベクトルタイルレイヤを使うことも可能です。
ここまでの練習で、線、ポリゴン、点のデータのスタイル作成を練習できました。
2-9. おまけの練習
最新の unvt/charites はMapLibre GL JSの 2.4.0を使っているので、3D Terrainの地図もプレビューできます。データソースとしてraster-demを指定して、style.tml中にterrainを追加します。ちょっと難しいですが、応用問題の練習として以下のような事例も紹介しておきます。
Exercise 3. YAMLファイルからJSONファイルへの出力
ここまで出来たらスタイル編集を終わりにし、JSONファイルに出力することも練習します。
ライブプレビューを止め、コマンドラインに戻りましょう。JSONへの出力は簡単で以下のようなコマンドで出来ます。
charites build charites-init/style.yml out-style.json
おめでとうございます。これでスタイル編集が終わったスタイルをJSON形式で得ることができました。
(もしも、スタイルの表現にエラーがあるとここでJSONが作成されません。)
まとめ
この記事ではどうやってMapbox/MapLibre向けのスタイルをUNVTのcharitesツールで編集するかを紹介しました。
ツールの使い方のみならず、Mapbox/MapLibreスタイルを理解する一助になれば幸いです。
謝辞
unvt/charitesの開発者の皆様、貢献者の皆様に感謝します。
Refernces
- Tools
- unvt/charites: https://github.com/unvt/charites
- Repository
- the files used in this practice: https://github.com/ubukawa/style-ex01
- Others
- UN Open GIS Initiative: http://unopengis.org/unopengis/main/main.php
- UN Open GIS Initaitive - DWG7 (smart maps): https://github.com/UNopenGIS/7
- Mapbox style specification: https://docs.mapbox.com/mapbox-gl-js/style-spec/
- MapLibre style specification: https://maplibre.org/maplibre-gl-js-docs/style-spec/
- nodejs: https://nodejs.org/en/