はじめに
Leafmap(プロットバックエンドは folium)でもPMTiles形式のベクトルタイルを表示できるらしいので、実際に試してみることにしました。
Leafmapについてですが、初めて扱った時の記事が以下になります。よろしかったらご参照下さい。
町丁目ポリゴンのベクトルタイル
TerraMap APIでも提供している町丁目ポリゴンデータを利用しました。tippecanoeでGeoJSONファイル等をベクトルタイルに変換する必要がありますが、今回は単一ファイルであるPMTiles形式を選びました。
変換作業に関しては以下記事をご参照下さい。地図表示させたいポリゴンのGeoJSONファイルをお持ちでしたら、同じようなことができると思います。
NginxによるPMTilesサーバー
NginxのDockerイメージを使ってPMTilesファイルを提供させます。ファイル構成は以下のようにしました。
root/
├── nginx.conf
├── Dockerfile
└── pmtiles
└── chomoku.pmtiles
Nginxの設定ファイル
CORSを有効にするため、設定を変更しています。
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
autoindex off; # ファイルリストの有無(必要に応じて)
# CORSヘッダーの設定 ※ 本番ではオリジンを適切に設定します
add_header Access-Control-Allow-Origin * always;
}
}
Dockerfile
FROM nginx:latest
ADD ./nginx.conf /etc/nginx/conf.d/default.conf
ADD ./pmtiles /usr/share/nginx/html
RUN echo "start nginx"
ビルドおよびコンテナ実行
docker build -t pmtiles-server .
docker run --name pmtiles-server -d -p 8080:80 pmtiles-server
地図アプリ作成
Leafmapを利用した地図アプリに関しては、Pythonでコーディングします。
環境準備
Pythonやpipを使えるようにして、まずはleafmap、geopandas、streamlitをインストールします。
pip install leafmap geopandas streamlit
Pythonコード
import leafmap.foliumap as leafmap
url = "http://localhost:8080/chomoku.pmtiles"
style = {
"version": 8,
"sources": {
"mvt_data": {
"type": "vector",
"url": "pmtiles://" + url,
"attribution": "PMTiles",
}
},
"layers": [
{
"id": "mvt_polygon",
"source": "mvt_data",
"source-layer": "chomoku-layer", # PMTilesのレイヤー名
"type": "fill",
"paint": {"fill-color": "#7fffd4", "fill-opacity": 0.2},
},
{
"id": "mvt_line",
"source": "mvt_data",
"source-layer": "chomoku-layer", # PMTilesのレイヤー名
"type": "line",
"paint": {"line-color": "#2e8b57", "line-width": 0.5},
},
],
}
def main():
# Mapオブジェクト作成
m = leafmap.Map(
# コントロールは最小限に
draw_control=False,
measure_control=False,
# 中心位置とズームレベル指定
center=(35.71967, 139.65313), zoom=9,
)
# PMTilesを表示
m.add_pmtiles(
url, name="chomoku", style=style, overlay=True, show=True, zoom_to_layer=False, tooltip=False
)
# 地図をStreamlitアプリ内に描画
m.to_streamlit(height=500)
if __name__ == "__main__":
main()
style
に関しては、ベクトルタイルのソースやレイヤーの細かい設定を書く必要がありますが、他の部分は比較的短いコードで済みました。
参考情報
動作確認
streamlit run app.py
アプリを起動すると、以下のような地図表示になりました。