MapLibreのSVGアイコン:ピクセルとシンボルサイズの確認
MapLibreのシンボルレイヤー用にSVGをデコードし、画像密度とアイコンサイズを制御。編集可能なマスターを残し、表示される形状と開口部を確認します。
MapLibre GL JSでSVGアイコン画像を使うには、ブラウザーのImageでSVGをデコードし、その画像をaddImageに渡して、シンボルレイヤーのicon-imageでIDを参照します。元のSVGは別に保管してください。登録したスタイル画像は描画用のピクセルを提供するもので、編集可能なSVGパスオブジェクトではありません。
現在の公式SVGシンボルの例に、このデコード経路が示されています。MapLibreではSVGアートワークを表示できないと一律に言うと、この方法を見落とします。この例では6.12.0に固定し、トークン不要の空白地図で、独自の中空エンブレムをテストします。
元データと登録画像を分ける
保管する元データには、内側の開口部を持つ一つの複合ひし形パスがあります。viewBoxは0 0 64 64のままです。幅と高さを64または128に明示した二つのコピーを作り、パスデータは同一に保ちます。
ブラウザーのデコードによって、それぞれのコピーが宣言した寸法の画像になります。MapLibreのaddImage APIは、HTMLImageElementやImageDataなどの画像オブジェクトを受け取れます。シンボルの形状指示としてSVGパスを受け取るものではありません。
色や輪郭を変えるときに、この違いが重要です。SVGマスターを編集し、修正した画像をデコードして、適切なAPIで地図の画像を更新してください。登録済みのピクセルを調べても、元のパスの構成は復元できません。ラスター画像を埋め込んだSVGのガイドでは、SVGの入れ物と編集可能な形状の、より広い違いを説明しています。

画像密度とアイコンサイズを一緒に選ぶ
二つの設定が、シンボルの公称画像枠に影響します。画像のpixelRatioは密度を表し、レイヤーのicon-sizeは結果のアイコンを拡大縮小します。現在のスタイル画像のメタデータとシンボルレイアウト仕様を参照してください。
中央配置、回転なし、テキストへのフィットなしのこのシンボルでは、公称枠は次のようになります。
logical width = decoded width / image pixelRatio * icon-size
logical height = decoded height / image pixelRatio * icon-size128×128の画像を比率2で登録すると、icon-sizeが1の場合、64×64の画像を比率1で登録した場合と同じ64×64の公称枠になります。前者の比率を1に変えると、枠は2倍になります。icon-sizeを1.5にすると、64×64の論理画像枠が96×96になります。
この枠には元画像の余白が含まれます。その中でエンブレムが小さく見える場合は、すべてのシンボルを大きくする前にSVGの範囲を確認してください。同じ比率でデコード画像を大きくしても、シンボルは大きくなります。入力寸法だけでは密度の方針にはなりません。
地図のキャンバスには独自のピクセル比率があります。addImageに渡す比率とは別です。この計測用ファイルでは、文書化されたMapオプションを使い、キャンバス比率を明示的に1に設定しています。ブラウザーのデバイスピクセル比率は2でした。これにより、スクリーンショットのデバイスピクセルをCSS寸法と考えることなく、以下の比較を切り分けています。
実際に塗られた範囲を比較する
WebGL 2を使うChromeで、五つのシンボルケースを描画しました。各地図には一つの点と同じ明るい背景があり、タイルもトークンもありません。両方の元SVGは、同一のパスを一つ持ち、埋め込み画像はありませんでした。
テラコッタ色のアートワークを測るため、実際のWebGLピクセルを読み取り、赤が強い色を探しました。条件は、赤が緑の1.35倍、青の1.6倍を超えることです。検出したバウンディングボックスの寸法を、キャンバスの内部バッファー寸法とCSS寸法の比率で割りました。これはしきい値で検出した塗り領域の計測であり、画像枠全体ではありません。
| デコード画像 | 画像比率 | icon-size | 公称枠 | 観察した塗りの範囲 |
|---|---|---|---|---|
| 64×64 | 1 | 1 | 64×64 | 62×62 CSS px |
| 128×128 | 1 | 1 | 128×128 | 126×126 CSS px |
| 128×128 | 2 | 1 | 64×64 | 62×62 CSS px |
| 64×64 | 1 | 1.5 | 96×96 | 94×94 CSS px |
| 128×128 | 2 | 1.5 | 96×96 | 94×94 CSS px |
縁のすべてのピクセルが色のしきい値を超えるわけではないため、計測した塗りの範囲は公称枠より小さくなります。これらのペアは、このテストファイルで意図したサイズ関係を示します。すべての密度やズームで、ピクセルの品質が同一であることを証明するものではありません。
登録画像の中央のアルファは、どのケースでもゼロでした。描画された地図では、その場所は背景レイヤー自体が不透明なため、アルファ255で背景色(244, 242, 232)を示しました。開口部を通して不透明な地図のピクセルが見えても、アイコンが透明度を失ったわけではありません。
これらの観察は、この元データ、ブラウザー、キャンバス設定、しきい値に限られます。特に細いストロークや小さな開口部がある場合は、予定の表示サイズで納品するアートワークをテストしてください。
トークン不要のシンボルのひな形をコピーする
この完全なHTMLを保存し、ローカルウェブサーバーで配信します。固定バージョンのライブラリーとCSSにはインターネット接続が必要ですが、地図にはタイルサービスもAPIキーも使いません。SVGはテキストとして埋め込み、データURLへエンコードします。
この例はimage.decode()を待つので、デコード成功後に登録します。スタイルの読み込み後に既知の画像を登録するため、この一つの固定エンブレムには、公式例の欠落画像リゾルバーは不要です。
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>MapLibre decoded SVG symbol</title>
<link rel="stylesheet"
href="https://unpkg.com/maplibre-gl@6.12.0/dist/maplibre-gl.css">
<style>#map { width: 360px; height: 280px; }</style>
<div id="map"></div>
<pre id="status">Loading…</pre>
<script type="module">
import * as ml from
'https://unpkg.com/maplibre-gl@6.12.0/dist/maplibre-gl.mjs';
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 64 64"><path fill="#c45b39" fill-rule="evenodd" d="M32 0 L64 32 L32 64 L0 32 Z M32 16 L16 32 L32 48 L48 32 Z"/></svg>`;
const image = new Image();
image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
try {
await image.decode();
const ratio = 2;
const iconSize = 1;
const map = new ml.Map({
container: 'map', center: [0, 0], zoom: 2, interactive: false,
attributionControl: false, fadeDuration: 0,
style: { version: 8, sources: {}, layers: [{
id: 'background', type: 'background',
paint: { 'background-color': '#f4f2e8' }
}] }
});
map.on('error', e => {
document.querySelector('#status').textContent = e.error.message;
});
await map.once('load');
map.addImage('emblem', image, { pixelRatio: ratio });
map.addSource('point', { type: 'geojson', data: {
type: 'Feature', geometry: { type: 'Point', coordinates: [0, 0] },
properties: {}
} });
map.addLayer({ id: 'emblem', type: 'symbol', source: 'point', layout: {
'icon-image': 'emblem', 'icon-size': iconSize, 'icon-overlap': 'always'
} });
await map.once('idle');
const registered = map.getImage('emblem');
document.querySelector('#status').textContent = JSON.stringify({
version: ml.getVersion(),
decoded: [image.naturalWidth, image.naturalHeight],
registered: [registered.data.width, registered.data.height],
imagePixelRatio: registered.pixelRatio,
logicalFrame: [image.naturalWidth / ratio * iconSize,
image.naturalHeight / ratio * iconSize]
}, null, 2);
} catch (error) {
document.querySelector('#status').textContent = String(error);
}
</script>
</html>ステータスには、デコードと登録の寸法[128, 128]、画像比率2、論理枠[64, 64]が表示されるはずです。これは公称枠を報告するもので、塗りのバウンディングボックスの計測値ではありません。iconSizeを1.5に変えると、96×96の枠になります。低密度の入力と比較するには、同じパスとviewBoxを保ったまま、SVGの幅と高さを64、ratioを1に変えます。
icon-imageは登録したIDと同じにしてください。アイコンが表示されない場合は、デコードと登録の成功を確認し、その後、ソース、レイヤー、表示状態、配置設定を調べます。一点だけのこの例ではicon-overlap: 'always'を使い、ほかのシンボルとの衝突から比較を独立させています。本番用スタイルでは、別の衝突処理が必要な場合があります。
提供方法に合う場合はDOMマーカーを使う
MapLibreはDOMマーカーを使う独自アイコンも文書化しています。この経路はスタイル画像を登録する代わりに、HTML要素を包み込みます。要素ベースのマーカーの手順がアプリケーションに合う場合に選び、ブラウザーのスタイルと配置は別に確認してください。
Mapbox Studioのベクターアイコン機能や、MapTiler SDKの例の説明を、このMapLibreのスタイル画像パイプラインに当てはめないでください。また、通常のフルカラーSVG画像は、sdfフラグを変えるだけで符号付き距離場にはなりません。密度設定は画像の解釈と表示を制御するもので、ピクセルを編集可能な輪郭に変えるものではありません。
利用先がPNGファイルを必要とする場合は、SharpによるSVG描画ガイドでラスターの納品用コピーの準備を説明しています。編集用には通常のSVGマスターを保管してください。インラインSVGと画像での提供も、操作のモデルが異なります。
アイコンがPNGやJPGでしか存在せず、編集可能なアートワークが必要なら、PerfectVectorでSVG輪郭を復元し、外側の形状と開口部を確認して、地図画像をデコードする前にそのマスターを残します。密度、シンボルサイズ、地理的位置は、引き続き地図コードが制御します。きれいなSVGがすでにあれば、直接デコードの手順に進めます。ベクター化ガイドでは、ラスター変換が役立つ場面を説明しています。
よくある質問
MapLibre GL JSはSVGアートワークをシンボルとして表示できますか? できます。現在の公式例は、ブラウザーのImageでSVGテキストをデコードし、その画像をシンボルレイヤーに登録します。元のSVGは登録画像と分けて保管してください。
大きい入力でアイコンも大きくなったのはなぜですか? 同じ画像ピクセル比率とicon-sizeを保ちながらデコード寸法を増やすと、公称枠が大きくなります。画像密度と表示倍率を意図的に組み合わせてください。
pixelRatioはシンボル内に編集可能なSVGパスを保持しますか? 保持しません。画像密度を表します。元のSVGを保管して編集し、その後、修正したアートワークを地図用にデコードしてください。
アイコンの穴の中の地図ピクセルが不透明なのはなぜですか? 不透明な背景レイヤーが、アイコンの透明な開口部を通して見える場合があります。登録画像のアルファは、完全に合成された地図キャンバスと分けて確認してください。
出典
- MapLibre — リモートSVGシンボルの表示 — 現在のSVGテキスト、ブラウザー画像、addImageを使う経路。
- MapLibre — Map API — 対応する画像オブジェクトと、実行時の画像登録。
- MapLibre — StyleImageMetadata — 画像密度とSDF解釈のメタデータ。
- MapLibre — シンボルレイアウト仕様 — アイコンの拡大縮小と衝突処理。
- MapLibre — MapOptions — 計測用ファイルの制御に使ったキャンバス設定。
- MDN — HTMLImageElement.decode — ブラウザーでの画像デコードの待機と、失敗の処理。
- MapLibre — Markersによる独自アイコンの追加 — 別のHTML要素ベースのマーカー手順。


