ドキュメント / 地図ビュー / 地図のスタイルを変える

地図のスタイルを変える

地図のベクタースタイルに「道路を白く」「ラベルを消す」「水域を暗く」といった調整を、ルールとして宣言的にかけるパッケージです。同じルールが Android・iOS でもそのまま使えます。

REACT
@mapconductor/js-vectorstyle
PROP
mapStyle
ESM / CJS
ESM のみ

01 · 概要

ルールは「どのレイヤーに(セレクタ)」「何をするか(パッチ)」の組の並びです。セレクタはレイヤー ID ではなく 役割(道路・水域・ラベル…)で書けます。OpenMapTiles・Shortbread・Mapbox Streets のスキーマは自動で見分けるので、スタイルごとに違うレイヤー ID を調べる必要はありません。

createVectorStyle() が返す値を、どの *MapView にも mapStyle として渡します。React では style が要素自身の CSS なので、名前は mapStyle です(Android・iOS では style)。

地図
どう効くか
必要なもの
MapLibre / Mapbox / MapTiler
スタイルを地図自身が読む。ルールを変えても差分だけを当て、タイルは読み直さない。
このパッケージだけ
そのほか(Google Maps・Leaflet・OpenLayers・ArcGIS・Cesium・HERE・MapKit・deck.gl …)
スタイルをラスタータイルに描いて重ねる。
rasteriser に VectorTileRasteriser

ラスタライザーを渡さずにベクター非対応の地図へ渡すと、何も描かずに黙るのではなく、診断に「このスタイルは使えない」と出します。

02 · インストール

terminalnpm
npm install @mapconductor/js-sdk-core @mapconductor/js-vectorstyle

ベクター非対応の地図でも使うなら、ラスタライザーの入った react-vectortile も入れます(ベクタータイルレイヤー の Service Worker の準備も要ります)。

terminalnpm
npm install @mapconductor/react-vectortile

ESM のみです。ルールのコンパイラは wasm(約 190 KB)で、import.meta.url からの相対で読み込みます。Vite ならそのまま動きます。別の場所から配るときは wasmUrl で指定します。

03 · 基本の使い方

document を省くと、地図がいま描いているスタイル('currentDesign')を調整します。下の例は MapLibre の既定のデザインを、道路だけが見える白黒の地図にします。

RoadsOnlyMap.tsxTypeScript · React
import { useMemo } from 'react';
import { buildStyleRules, createVectorStyle, LayerRole } from '@mapconductor/js-vectorstyle';
import { MapLibreMapView2D, useMapLibreViewState } from '@mapconductor/react-for-maplibre';

export function RoadsOnlyMap() {
  const state = useMapLibreViewState();
  const mapStyle = useMemo(
    () => createVectorStyle({
      rules: buildStyleRules((r) => {
        r.all({ color: '#000000' });
        r.role(LayerRole.label, { visible: false });
        r.role(LayerRole.roadCasing, { color: '#303030' });
        r.role(LayerRole.road, { color: '#ffffff', widthScale: 1.4 });
      }),
    }),
    [],
  );

  return (
    <MapLibreMapView2D
      state={state}
      mapStyle={mapStyle}
      onStyleDiagnostics={(messages) => console.warn(messages)}
    />
  );
}

自前のスタイルを使うときは document に { url } か { text } を渡します。

04 · ルールの書き方

ルールは上から順に当たり、CSS と同じく項目ごとに後のものが勝ちます。まず all で全体を決め、役割ごとに上書きしていくのが基本です。

TypeScriptTypeScript
buildStyleRules((r) => {
  r.all({ colorFilter: { darken: 0.55 } });
  r.role(LayerRole.water, { color: 'rgb(10,28,43)' });
  r.role(LayerRole.road, { color: '#d0d0d0' });
  r.layerId('poi-*', { visible: false });
  r.kind('symbol', { opacity: 0.8 });
});
セレクタ
ビルダー
説明
all
r.all(patch)
すべてのレイヤー。
{ role }
r.role(LayerRole.road, patch)
役割。background・water・waterway・land・landuse・park・building・road・road-casing・rail・transit・boundary・aeroway・label・poi。
{ layerId }
r.layerId('poi-*', patch)
レイヤー ID。* と ? が使える。
{ sourceLayer }
r.sourceLayer('water', patch)
タイルの source-layer 名。
{ kind }
r.kind('symbol', patch)
レイヤーの種類。background・fill・line・circle・symbol・other。
anyOf / allOf / not
r.where(selector, patch)
組み合わせ。
パッチ
型
説明
visible
boolean
表示・非表示。
color
string
レイヤーの種類に合った色(塗り・線・文字とアイコン・背景)。
colorFilter
{ desaturate } | { darken } | { lighten } | { invertLightness } | { mix }
元の色に対する変換。
opacity
0–1
不透明度。
widthScale
number
線幅・円の半径の倍率。
filter
MapLibre の式
レイヤーのフィルタを置き換える。
minZoom / maxZoom
number
表示するズームの範囲。
properties
Record<string, unknown>
スタイル仕様のプロパティを名前で直接。最後に当たる。

ルールを JSON で持つ

ルールは JSON の文書でもあります。サーバーから配ったり、アプリの版をまたいで保存したりするときは、この形で持って parseStyleRules() で読みます。同じ文書が Android・iOS でも読めます。

night.rules.jsonJSON
{
  "schemaVersion": 1,
  "rules": [
    { "selector": "all", "patch": { "colorFilter": { "darken": 0.55 } } },
    { "selector": { "role": "water" }, "patch": { "color": "rgb(10,28,43)" } }
  ]
}
TypeScriptTypeScript
import { createVectorStyle, parseStyleRules } from '@mapconductor/js-vectorstyle';

const rules = parseStyleRules(await (await fetch('/night.rules.json')).text());
const mapStyle = createVectorStyle({ rules });

05 · ベクター非対応の地図で使う

VectorTileRasteriser を rasteriser に渡すと、スタイルをラスタータイルに描いて重ねます。プロバイダ自身の地図は None のデザインにして消しておきます。

TypeScriptTypeScript · React
import { useMemo } from 'react';
import { createVectorStyle } from '@mapconductor/js-vectorstyle';
import { VectorTileRasteriser } from '@mapconductor/react-vectortile';
import { GoogleMapDesign, GoogleMapView2D, useGoogleMapViewState } from '@mapconductor/react-for-googlemaps';

const state = useGoogleMapViewState({
  apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
  mapDesignType: GoogleMapDesign.None,
});
const rasteriser = useMemo(() => new VectorTileRasteriser(), []);
const mapStyle = useMemo(
  () => createVectorStyle({
    document: { url: 'https://tiles.versatiles.org/assets/styles/colorful/style.json' },
    rules,
    rasteriser,
  }),
  [rules, rasteriser],
);

<GoogleMapView2D state={state} mapStyle={mapStyle} style={{ height: 480 }} />
注意
ラスタライザーは同じものかどうかで比べます。描画のたびに new すると別のスタイルとみなされ、地図が毎回作り直されます。useMemo などで1つを持ち続けてください。

06 · 主なオプション

オプション
既定値
説明
document
'currentDesign'
調整するスタイル。{ url, headers? }・{ text }・'currentDesign'。
rules
—
かけるルール。NO_STYLE_RULES なら元のまま。
rasteriser
—
ベクター非対応の地図で描くためのもの。
onUnsupported
'report'
地図が差分を受け付けないとき。'reload' なら調整済みの文書を丸ごと渡す(正しいが重い)。
onDiagnostics
—
当たったレイヤーの数、何にも当たらなかったルール、地図が拒んだ調整。
wasmUrl
—
コンパイラの wasm の場所。

診断は *MapView の onStyleDiagnostics でも受け取れます。省くとコンソールに出ます。「何にも当たらなかったルール」は、見た目では「ほとんど効いている」としか分からないので、作っている間は見えるところに出しておくのがおすすめです。

関連ページ