maplibre-source-wiring について
MapLibre の開発者向けに、データソースとマップスタイルの接続方法を解説します。タイル参照、レイヤースキーマ、アセット設定に加え、空白マップなどの原因調査も扱います。
主な機能
- 01TileJSON URL とタイルテンプレートの選択
- 02ベクタータイルの source-layer 名の確認
- 03レイヤーの描画順序の制御
- 04グリフとスプライトの設定
- 05ラスタータイルとフィーチャーステートの診断
- 06クロスオリジンリクエストの確認
活用シーン
- 01空白マップや未描画レイヤーの調査
- 02カスタムデータのマップスタイルへの追加
- 03ベースマップの縮尺やレイヤー順序の修正
- 04アイコン欠落、ホバー状態、タイル読み込みの診断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ maplibre/ maplibre-agent-skills --skill maplibre-source-wiringインストール後、Claude Code で/maplibre-source-wiringを入力して読み込まれたか確認します。
詳細
MapLibre ソースの接続
タイル URL またはデータファイルとスタイルがあるのに、地図が真っ白になる、縮尺が合わない、あるいは描画順序が正しくない場合があります。このスキルでは、ソースをスタイルに正しく接続する方法と、外から見ると同じように見えるさまざまな失敗モードを説明します。
このスキルを使う場面
ソースはすでに設定済みなのに、エラーが出ないまま地図が正しく表示されない場合に使います。原因が分かる前に確認できる症状は次のとおりです。
- 地図が真っ白になる、または追加したレイヤーが何も描画せず、コンソールにもエラーがない
- プロバイダー独自のスタイルでは動作するタイルソースに、カスタムスタイルを適用しても何も描画されない
- ベースマップがぼやけている、または上に重ねたすべての要素と縮尺が異なる
- 追加したデータが道路名を覆ってしまう
- 地図のほかの部分は正常に描画されるのに、アイコンだけが表示されない
- ホバーやクリックによるハイライトがまったく動作せず、エラーも発生しない
- タイルエンドポイントはあるものの、どのソースタイプが必要なのか、あるいは
tilesを手書きする代わりにurlでTileJSONを指定するべきなのか分からない
このスキルの対象外です。 フォントが正しく表示されない、スクリプトが見つからない、glyph PBF をセルフホストする場合は、maplibre-fonts-glyphs を参照してください。設計中のスタイルの色、種類、描画順序を決める場合は、maplibre-cartography を参照してください。データセットを GeoJSON とベクタータイルのどちらで扱うべきかを決める場合は、maplibre-tile-sources を参照してください。
タイルの指定方法:url と tiles
タイルはズーム(Z)、列(X)、行(Y)で指定します。これはラスタータイルとベクタータイルのソースに共通する方式です。詳しくはOpenStreetMap の Wikiを参照してください。MapLibre のソースでは、tiles の URL テンプレートでタイルを直接指定するか、TileJSON エンドポイントを指す url を指定します。
TileJSON エンドポイントが利用できる場合は、url を優先してください。 MapLibre はドキュメントを取得し、タイル URL テンプレート、ズーム範囲、範囲、帰属表示、さらにベクタータイルの場合は利用可能な source-layer を自動的に読み込みます。Martin や tileserver-gl などのタイルサーバーは、配信する各タイルセットの TileJSON エンドポイントを生成します。多くのホスト型プロバイダーも同様です。
TileJSON エンドポイントがない場合、たとえば URL テンプレートを直接提供するラスタータイルサービスでは、tiles 配列を使い、minzoom、maxzoom、帰属表示などのメタデータをソース定義に自分で指定してください。
TileJSON エンドポイントを指す url:
{
"type": "vector",
"url": "https://example.com/tiles.json"
}
tiles 配列:
{
"type": "vector",
"tiles": ["https://example.com/tiles/{z}/{x}/{y}.pbf"],
"minzoom": 0,
"maxzoom": 14
}
{z}、{x}、{y} は、リクエストを行う前に MapLibre が各タイルのズーム、列、行に置き換えるトークンです。波括弧が残ったままのテンプレートをブラウザーに貼り付けても、実際のタイルはリクエストされないため、ステータスコードからサーバーの状態は分かりません。サーバーを手動で確認するには、/0/0/0.pbf のように、ソースのズーム範囲内にある実際のタイルをリクエストしてください。
tiles を手動で設定する場合の問題は、ズーム範囲を指定しないと MapLibre がその範囲を認識できず、maxzoom: 22 を前提にすることです。その結果、タイルセットに存在しないズームレベルをリクエストし、空のレスポンスが返されます。このため、TileJSON エンドポイントがある場合は url を使うのが基本です。(PMTiles でも同じルールが当てはまり、結果はさらに顕著になります。詳しくは maplibre-pmtiles-patterns を参照してください。)
何も表示されない場合:source-layerとタイルスキーマ
動作しているタイルソースにカスタムスタイルを適用しても何も表示されない場合、最もよくある原因はsource-layerの不一致です。
ベクタータイルソースには、transportation、water、landuseなどの名前付きレイヤーが含まれており、そのソースから描画するスタイルレイヤーには、いずれかの名前を正確に指定する必要があります。
{
"id": "roads",
"type": "line",
"source": "basemap",
"source-layer": "transportation"
}
ベクターソースではsource-layerが必須で、タイルスキーマと完全に一致している必要があります。入力ミスや別のスキーマのレイヤー名を指定しても、エラーも出力も発生せず、そのレイヤーは何も描画しません。
TileJSONで実際の名前を確認します。 ベクターソースの場合、TileJSONのvector_layersフィールドには、利用可能な各source-layer、その属性フィールド、ズーム範囲が記載されています。これは存在する場合に信頼できる参照先です。TileJSON 3.0ではベクタータイルセットに必須ですが、2.xのドキュメントはこの要件より前のものであり、プロバイダーによって提供状況にばらつきがあります。これがなくてもスキーマが存在しないわけではありません。スキーマ名(以下を参照)を特定し、公開されているレイヤー一覧を参照してください。プロバイダーの既成スタイルURLを使う場合、スキーマはすでに適切に設定されています。不一致が起きるのは、自分でレイヤーを記述した場合だけです。
定義済みのタイルスキーマ
カスタムスタイルを作成するには、タイルスキーマ、つまりソースレイヤー名とそのプロパティを把握する必要があります。一般的なスキーマは次のとおりです。
- OpenMapTiles — OpenStreetMapデータを基にした、最も広く採用されているスキーマです。豊富で詳細な構成で、
transportation、water、landuse、poiなどのソースレイヤーがあります。コミュニティスタイルのエコシステムが最も充実しており、多くのスタイルがこのスキーマを対象としています。 - Shortbread — 特定のベンダーに依存しない、最小限で相互運用可能な設計のオープン標準です。OpenMapTilesよりもシンプルな構造で、スタイルをゼロから作成する場合のすっきりした基盤になります。
- Protomaps — Protomaps PMTilesのベースマップエコシステム向けに特化して設計されています。
earth、water、roads、placesなどのソースレイヤーを持つ、フラットでシンプルな構造で、サーバーレス配信に最適化されています。公開レイヤー一覧:docs.protomaps.com/basemaps/layers。
これらはいずれも、ドキュメントとしてレイヤー一覧を公開しています(「参考資料」を参照)。機械で読み取り可能なバージョンマーカーを備えたものはないため、スキーマを確認するにはページを再度読み込む必要があり、変更を定期的に確認することもできません。
Planetilerやtippecanoeでタイルを生成すると、出力ファイルのMBTilesまたはPMTilesにTileJSONメタデータが埋め込まれます。Martinのようなタイルサーバーはこのメタデータを読み取り、TileJSONエンドポイントとして自動的に公開します。
レイヤーの順序:ラベルの下に描画する
レイヤーは、スタイルに記述された順に下から上へ描画されます。第2引数なしでmap.addLayer()を呼び出すと、そのレイヤーはすべての要素の上に追加され、道路名も覆ってしまいます。そのため、この方法で追加したデータオーバーレイはベースマップのラベルを隠します。対処するには、最初のsymbolレイヤーのIDをaddLayerの第2引数に渡します。IDはハードコードせず、プログラムで取得してください(road-labelなどの名前はスキーマ固有のため、ベースマップを変更した時点で機能しなくなります)。ベクターレイヤーの後に追加したラスターレイヤーも、同じ理由でそれらを覆い隠します。
挿入パターンの詳しい説明と、スタイルをゼロから作成する場合の標準的なレイヤー順序については、maplibre-cartographyを参照してください。
ラベルとアイコンが表示されない場合:glyphs と sprite
スタイルルートの 2 つのプロパティで、シンボルレイヤーの描画に使用するアセットを指定します。
glyphs— フォントスタックの URL テンプレートです:"glyphs": "https://example.com/fonts/{fontstack}/{range}.pbf"sprite— スプライトシートとメタデータのベース URL で、.jsonと.pngの両方を提供します:"sprite": "https://example.com/sprites/basic"
ホスト型プロバイダーの既成スタイル URL には、これらが含まれています。カスタムスタイルを作成する場合やセルフホストする場合は、自分で指定する必要があります。
この 2 つは未設定時の挙動が異なり、その違いから症状を逆にたどって原因を特定できます。 GL JS 5.11.0 以降では、glyphs が未設定でもテキストは消えません。MapLibre は代わりにローカルのシステムフォントで描画するため、テキストが表示されないのではなく、異なる書体で表示されます。ラベルが表示されているものの見た目が違う場合は glyphs を確認してください。完全に表示されない場合は該当しません。sprite が未設定の場合、アイコンが見つからないたびにコンソール警告(Image "<id>" could not be loaded)が記録され、アイコンは一切描画されません。map.hasImage(id) はそれぞれ false を返します。sprite の URL の読み込みに失敗した場合も、エラーが記録されます。
フォールバックの仕組みと制限(GL JS のみが対象で、Native では引き続き PBF の配信が必要です)、フォントスタック、セルフホストと生成の違い、スクリプトの対応状況については、maplibre-fonts-glyphs を参照してください。
ラスターソース:tileSize と命名に関する落とし穴
ラスター固有の注意点が 2 つあります。どちらもエラーなしで設定できますが、誤った描画や誤った前提につながります。
tileSize のデフォルトは 512 です。従来の OSM タイルは 256 です。 tile.openstreetmap.org やその他の従来型スリッピーマップタイルサーバーは 256px のタイルを配信しますが、MapLibre のラスター tileSize のデフォルトは 512px です。256px のソースに tileSize: 256 を指定しなくてもエラーにはなりませんが、有効なズームレベルがずれて描画され、画像とラベルが 1 ズームレベルずれて表示されます。エラーや警告はありません。
{
"type": "raster",
"tiles": ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
"tileSize": 256
}
ラスターエンドポイントの名前は、その種類を示すものではありません。 「hillshade」や「terrain」などの名前が付いたエンドポイントが、必ずしも raster-dem ソースとは限りません。raster-dem では、タイルが PNG または WebP 内にピクセルパックされた RGB として標高をエンコードしている必要があります(Mapbox または Terrarium エンコーディング)。TileJSON に encoding フィールドがある場合は、その値でエンコーディングの種類を確認できます。そのエンコーディングを保持できないタイル形式(たとえば JPEG)で、encoding フィールドもない場合、エンドポイント名にかかわらず通常の raster 画像です。「hillshade」エンドポイントは、多くの場合、MapLibre がクライアント側で陰影を付けるための生の標高データではなく、あらかじめレンダリングされた陰影起伏図の 画像 です。名前を raster-dem の根拠とする前に、タイル形式と encoding フィールドの有無を確認してください。
フィーチャーの状態:ソースには id が必要で、通常は promoteId で設定します
setFeatureState と feature-state 式は、フィーチャーの id(フィーチャーオブジェクトのトップレベルメンバーであり、properties 内の値ではありません)をキーにします。フィーチャーに id がないソースでは、setFeatureState が状態を紐付ける対象がないため、エラーが表面化せずに失敗します。コンソールエラーは出ず、ペイント式も実行されず、getFeatureState は空を返します。
すでにキーとして使っているプロパティを promoteId に設定してください。 MapLibre にそのプロパティをフィーチャーの id として使わせる設定であり、識別子が properties にある場合の正しい方法です。
map.addSource('parcels', {
type: 'geojson',
data: parcels,
promoteId: 'parcel_id'
});
map.setFeatureState({ source: 'parcels', id: 'APN-1234' }, { hover: true });
ベクターソースでは、promoteId に、すべてのソースレイヤーに適用されるプロパティ名を指定するか、{<sourceLayer>: <propertyName>} 形式のオブジェクトを指定します。[9]
業務キーがある場合は、generateId や手書きの id を使わないでください。 どちらも解決策のように見えますが、今回のケースではどちらも機能しません。
generateId: trueはfeatures配列内のインデックスに基づいて id を割り当て、既存の値は上書きします。[9]setDataによって並べ替え、フィルタリング、追加が行われると id が安定しないため、更新後に状態が誤ったフィーチャーへ気づかないうちに紐付けられます。- トップレベルの
idを記述する方法が機能するのは、整数の場合だけです。promoteIdを使わない場合、フィーチャーの id は「整数、または整数にキャストできる文字列」である必要があります。[9]APN-1234のようなキーは受け入れられますが、一致することはありません。promoteIdを使えば、値には任意のプリミティブ型を指定できます。
CORS
タイル、グリフ、スプライトが別のオリジンにある場合、サーバーは CORS ヘッダー(Access-Control-Allow-Origin)を送信する必要があります。そうしないとブラウザーがリクエストをブロックし、地図が空になったり、ラベルが表示されなかったりします。
ホスト型プロバイダーでは、CORS は自動的に処理されます。セルフホスト型サーバーや静的ストレージでは、サーバーまたは CDN で CORS を設定してください。範囲リクエストを使うソース(PMTiles)では、さらに Access-Control-Allow-Headers: Range が必要です。
空白の地図を診断する
以下のリストを順に確認してください。各症状は重なり合うことがよくあります。
| 症状 | 最初に確認する項目 |
|---|---|
| 何も表示されず、ネットワークに失敗したリクエストがある | CORS ヘッダー、タイル URL 自体(ネットワークタブの 404) |
| 何も表示されず、ネットワークに 200 が表示される | source-layer 名と TileJSON の vector_layers の照合 |
| ズームインするとタイルが表示された後に消える | 手動で設定した tiles ソースにズーム範囲がない。代わりに url を使う |
| タイルは表示されるが、テキストのフォントが違う | glyphs がない、またはその URL の読み込みに失敗している |
| タイルは表示されるが、テキストがまったく表示されない | どのシンボルレイヤーにも text-field がない、または GL JS が 5.11 より古い |
| タイルは表示されるが、アイコンがない | スタイルのルートに sprite がない |
| データは描画されるが、ラベルが隠れる | レイヤーの順序。最初の symbol レイヤーより前に挿入する |
| ベクターソースは何も描画されないが、ラスタは正常 | source-layer がまったくない。ベクターソースでは必須 |
| ラスタータイルのズームレベルが 1 段ずれる | 従来型の 256px ソースで tileSize: 256 がない(デフォルトは 512) |
setFeatureState が何もせず、エラーも出ない | フィーチャーに id がない。識別プロパティを promoteId に設定する |
関連スキル
- maplibre-tile-sources — データセットに GeoJSON とタイルのどちらを選ぶか。
- maplibre-pmtiles-patterns —
pmtiles://プロトコルの登録と、PMTiles 固有のソース設定。 - maplibre-fonts-glyphs — フォントスタック、グリフエンドポイント、文字体系のカバレッジ。
- maplibre-sprites-icons —
spriteURL の形式、複数のシートの読み込み、スプライトアセットのセルフホスト、ルートシールド。 - maplibre-cartography — レイヤー注入パターンの詳細と、カスタムスタイルの標準的なレイヤー順序。
参考資料
- MapLibre スタイル仕様 — maplibre.org/maplibre-style-spec/
- TileJSON 仕様 — GitHub の仕様リポジトリ。バージョン 3.0(2021 年 8 月)では、ベクタータイルセットに
vector_layersが必須になりました - スリッピーマップのタイル命名規則(Z/X/Y 方式) — OpenStreetMap wiki
- OpenMapTiles スキーマ — openmaptiles.org/schema/
- Shortbread タイルスキーマ — shortbread-tiles.org
- Protomaps ベースマップレイヤー — docs.protomaps.com/basemaps/layers
- Martin タイルサーバー(TileJSON エンドポイント)— maplibre.org/martin/
- MapLibre GL JS ドキュメント — maplibre.org/maplibre-gl-js/docs/
promoteId、generateId、feature-state— スタイル仕様:sources および expressions
このスキルはある時点のスナップショットです。 一次情報(上記の参考資料、MapLibre の最新ドキュメント、または MapLibre を実行したときの挙動)と矛盾する場合は、一次情報を優先してください。それに従ったうえで、情報源と MapLibre のバージョンを明記して不一致を報告してください。インストール済みのコピーを編集しても他の人の役には立たず、次回の更新で上書きされます。