tilemaker で vector tile を self hosting
tilemaker というツールで vectortile を生成をして自前で hosting する練習。
動く手順を記録。
- memory 16G くらい
いちおう gh-pages で self-host するところまでたどり着いてた
sample repository
gh-pages
このリポジトリの説明。
さすがに gh-action でマップタイトルを生成するのは無謀なので、
pubilc/tiles に gzip で圧縮された maptile をコミットしている。
gh-action で gzip を解凍している。
(完全に海の tile がサイズ0 なのに注意)
走り書き
config-example.json 最小限の動作確認
vector tile を生成
ビルド済みの tilemaker を入手
プラットフォームに合わせて適当に。
元データを入手
から
japan-latest.osm.pbf
をダウンロードしました(2G弱)。
tilemaker を実行する
4つの引数があります。
- input: japan-latest.osm.pbf です
- output: 出力ディレクトリを指定します。無くても作ってくれます。
- config: tilemakerの resources/config-example.json
- process: tilemakerの resources/process-example.lua
# powershell の例
PS1> .\tilemaker\build\RelWithDebInfo\tilemaker.exe --input .\japan-latest.osm.pbf --output example --config .\tilemaker\resources\config-example.json --process .\tilemaker\resources\process-example.lua
i7 + memory 16G で 20分くらいかかった。
zoomlevel 12,13,14 が生成されていて、それぞれの容量は以下の通り。zoom するごとに 2倍に増える?
- 12 => 127 MB
- 13 => 245 MB
- 14 => 555 MB
生成した vector tile を使う
構成
+ example
+ 12
+ 13
+ 14
+ index.html
+ main.ts
+ package.json
> npm init -y
> npm install -S vite typescript maplibre-gl
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>map</title>
<style>
#map {
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="module" src="main.ts"></script>
</body>
</html>
import maplibregl from 'maplibre-gl';
document.addEventListener("DOMContentLoaded", async (event) => {
const port = location.port
? (':' + location.port) : '';
const baseUrl = `${location.protocol}//${location.hostname}${port}`;
new maplibregl.Map({
container: 'map',
style: {
"version": 8,
"name": "Basic",
"sources": {
"openmaptiles": {
"type": "vector",
"tiles": [`${baseUrl}/example/{z}/{x}/{y}.pbf`] // 👈 tilemaker の生成物
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": { "background-color": "hsl(47, 26%, 88%)" }
},
{
"id": "transportation",
"type": "line",
"source": "openmaptiles",
"source-layer": "transportation",
"layout": { "visibility": "visible" },
"paint": {
"line-color": "hsl(34, 12%, 66%)",
"line-opacity": {
"base": 1,
"stops": [
[11, 0],
[16, 1]
]
}
}
},
],
},
center: [139.7024, 35.6598],
zoom: 14,
minZoom: 12,
maxZoom: 14,
});
});
動作確認
> npx vite
背景色しか出ない。
gzip 圧縮への対処
console を見ると pbr の parse error が。
どうも gzip に圧縮されているらしい。
Unable to parse the tile at http://xxx/{zoom}/{x}/{y}.pbf,
please make sure the data is not gzipped and that you have configured the relevant header in the server
確かに。
> D:\msys64\usr\bin\file.exe .\example\14\13788\7042.pbf
.\example\14\13788\7042.pbf: gzip compressed data, from TOPS/20, original size modulo 2^32 141
tilemaker/resources/config-example.json
{
"layers": {
"waterway": { "minzoom": 11, "maxzoom": 14 },
"transportation": { "minzoom": 12, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0001, "simplify_ratio": 2.0 },
"building": { "minzoom": 14, "maxzoom": 14 },
"poi": { "minzoom": 13, "maxzoom": 14 }
},
"settings": {
"minzoom": 12,
"maxzoom": 14,
"basezoom": 14,
"include_ids": false,
"name": "Tilemaker example",
"version": "0.1",
"description": "Sample vector tiles for Tilemaker",
"compress": "gzip", // 👈 これ
"metadata": {
"json": { "vector_layers": [
{ "id": "transportation", "description": "transportation", "fields": {"class":"String"}},
{ "id": "waterway", "description": "waterway", "fields": {"class":"String"}},
{ "id": "building", "description": "building", "fields": {}}
] }
}
}
}
*.pbf
を *.pbf.gz
にリネーム。
# powershell でまとめてリネームする例
> cd .\example\
example> Get-ChildItem -Recurse "*.pbf" | ForEach-Object {Move-Item $_ "$_.gz"}
style.sources
を書き換え
new maplibregl.Map({
container: 'map',
style: {
"version": 8,
"name": "Basic",
"sources": {
"openmaptiles": {
"type": "vector",
"tiles": [`${baseUrl}/example/{z}/{x}/{y}.pbf.gz`] // 👈 .pbf.gz
動きました。
おそらく example を openmaptiles に変えて、
長い style.json を既存の地図から頂いてくればそれなりの地図が出ると思われます(まだやっていない)。
config-openmaptiles.json
動作確認ができたので今度は、config-openmaptiles.json
やってみます。
手順は、こちらにあります。
海岸データの取得
から
water-polygons-split-4326.zip
をダウンロードします。
解凍してフォルダ名を coastline
に変えます( config-openmaptiles.json の記述に合わせる )。
# powershell の例
PS1> .\tilemaker\build\RelWithDebInfo\tilemaker.exe --input .\japan-latest.osm.pbf --output openmaptiles --config .\tilemaker\resources\config-openmaptiles.json --process .\tilemaker\resources\process-openmaptiles.lua
0 ~ 14 zoom が生成されました。
生成した vector tile を使う(openmaptiles)
前回の実験の tiles パスだけ変更
動いた。
しかし、スタイルが無いので表示は同じ。
font 入手
git clone https://github.com/klokantech/klokantech-gl-fonts fonts
style 入手
から
MapTiler Basic
の style.json
を入手。
2か所修正します。
const port = location.port
? (':' + location.port) : '';
const baseUrl = `${location.protocol}//${location.hostname}${port}`;
const tiles = `${baseUrl}/openmaptiles/{z}/{x}/{y}.pbf
const glyphs = `${baseUrl}/fonts/Klokantech {fontstack}/{range}.pbf`
海岸線、フォント付きで動作しました。
trouble
フォントの設定ミスがある場合・・・
console に次のエラーがでました。
unimplemented type: 4
network を見ると 404。
Discussion