Maputnikでベクトルタイルのスタイルファイルを作成する

# はじめに
[こちらの記事](https://qiita.com/k96mz/items/1f7e0f8e6e41e6a78cc6)で作成したベクトルタイルを地図上に表示したいと考え、そのために必要なスタイファイルの作成手順を説明します。[Maputnik](https://maputnik.github.io/)を使用します。

# Maputnikを使用したスタイルファイルの作成手順

## ベクトルタイルの読み込み
Maputnikを開いたら、「Data Sources」 > 「Add New Srouce」に以下の通り入力してベクトルタイルを読み込みます。

| プロパティ  | 値 | 説明 |
|:-:|:-:|:-:|
| Source ID  | v | 任意の値  |
| Source Type  | Vector(XYZ URLs)  | 既定値  |
| Tile URL | https\://k96mz.github.io/makeVectorTiles/Data/VTpractice/{z}/{x}/{y}.pbf | ベクトルタイルのURL |
| Min Zoom | 0 | 最小ズーム値  |
| Max Zoom | 4 | 最大ズーム値  |

:::note info
Source Typeは、Vector(XYZ URLs)とありますが、Tile URLは、{z}/{x}/{y}の順番となることに注意してください。
:::

GitHubに格納しているベクトルタイルを読み込みますので、GitHub Pagesの設定でベクトルタイルを公開している必要があります。

## スタイルを作成する
次にスタイルファイルを作成します。「Add Layer」から以下の通り入力します。

◯海岸線
ID: coastl（任意の値、今回はSource Layerと同じ名前とした）
Type: Line（データタイプが線であるため）
Source: v（先ほど追加したソースを指定）
Source Layer: coastl（ベクトルタイル作成時に指定したレイヤの名称を記載）

◯陸域
ID: landmass
Type: Fill（データタイプが面であるため）
Source: v
Source Layer: landmass（ベクトルタイル作成時に指定したレイヤの名称を記載）

color：rgba(195, 176, 176, 1)　（適当に値を指定した）

◯河川
ID: riverl
Type: Line
Source: v
Source Layer: riverl（ベクトルタイル作成時に指定したレイヤの名称を記載）

color: blue
width: 2

以下の図のような地図が表示されます。
![スクリーンショット 2024-08-01 15.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/6f60d853-7a9e-ab4b-95f6-7f4c6d46dfef.png)


作成したスタイルファイルは、「Export」 > 「Download Style」でダウンロード出来ます。
ダウンロードされたスタイルファイルは以下です。

```json:download_style.json
{
  "version": 8,
  "name": "Empty Style",
  "metadata": {"maputnik:renderer": "mlgljs"},
  "sources": {
    "v": {
      "type": "vector",
      "tiles": [
        "https://k96mz.github.io/makeVectorTiles/Data/VTpractice/{z}/{x}/{y}.pbf"
      ],
      "minzoom": 0,
      "maxzoom": 4
    }
  },
  "sprite": "",
  "glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "coastl",
      "type": "line",
      "source": "v",
      "source-layer": "coastl",
      "maxzoom": 5
    },
    {
      "id": "landmass",
      "type": "fill",
      "source": "v",
      "source-layer": "landmass",
      "maxzoom": 5,
      "paint": {"fill-color": "rgba(195, 176, 176, 1)"}
    },
    {
      "id": "riverl",
      "type": "line",
      "source": "v",
      "source-layer": "riverl",
      "maxzoom": 5,
      "paint": {"line-color": "blue", "line-width": 2}
    }
  ],
  "id": "dsyugj9"
}
```


スタイリングをした地図は、こちらの[Maputnik](https://maputnik.github.io/editor/?style=https://k96mz.github.io/makeVectorTiles/style/download_style.json)のリンクから見られます。

:::note info
### sourcesの"minzoom"と"maxzoom"について
例えば、"minzoom"が1だと、レイヤ（例えばcoastl）がズームレベル0~1の間は表示されなくなります。
しかし例えば、"maxzoom"が4でも個々のレイヤ（例えばcoastl)のmaxzoomが5の場合は、5までは表示されます。つまり、sourcesのmaxzoomの設定に意味はないのだと思います。
例えば、coastlのmaxzoomが8だと、ズームレベル8までは表示されます。
:::


# MapLibre GL JSで表示する
[MaplLibre GL JSのExampleのページ](https://maplibre.org/maplibre-gl-js/docs/examples/simple-map/
)で紹介されているコードを使用します。

```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Display a map</title>
    <meta
      property="og:description"
      content="Initialize a map in an HTML element with MapLibre GL JS."
    />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="stylesheet"
      href="https://unpkg.com/maplibre-gl@4.5.0/dist/maplibre-gl.css"
    />
    <script src="https://unpkg.com/maplibre-gl@4.5.0/dist/maplibre-gl.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }
      html,
      body,
      #map {
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      const map = new maplibregl.Map({
        container: "map", // container id
        style:
          "https://k96mz.github.io/makeVectorTiles/style/download_style.json", // style URL
        center: [0, 0], // starting position [lng, lat]
        zoom: 1, // starting zoom
        maplibreLogo: true,
        hash: true,
      });

      //UI
      map.addControl(new maplibregl.NavigationControl(), "bottom-right");
      map.addControl(new maplibregl.ScaleControl());

      //debug
      map.showTileBoundaries = true;
      map.showCollisionBoxes = false;
    </script>
  </body>
</html>
```

サンプルコードのスタイルファイルの参照先は変更しています。
また、hash, UI, debugの記述も追記しています。

作成した地図は[こちら](https://k96mz.github.io/makeVectorTiles/index.html)で見られます。
Tippecanoeは、デフォルトで入力データの投影法をEPSG:4326（WGS84）とみなし、作成されるベクトルタイルは自動的にEPSG:3857（Web Mercator）に変換されます。そのため、作成された地図は、以下のように高緯度のグリーンランドなどが大きく表示されています。

![スクリーンショット 2024-08-23 16.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/255546ee-7fdc-54cb-0318-84a691be26b5.png)


下図は、入力データの投影法EPSG:4326（WGS84）ですが、違いが大きいですね。

![スクリーンショット 2024-08-23 16.54.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/6ac3eb4f-ee19-b130-c9ee-200c4d82c8d8.png)


# Reference
https://qiita.com/k96mz/items/1f7e0f8e6e41e6a78cc6

https://qiita.com/k96mz/items/a39625d616ea84d750ee