지도 스타일 바꾸기
지도의 벡터 스타일에 「도로를 흰색으로」「라벨 숨기기」「수역을 어둡게」 같은 조정을 규칙으로서 선언적으로 적용하는 패키지입니다. 같은 규칙을 Android·iOS에서도 그대로 사용할 수 있습니다.
01 · 개요
규칙은 「어떤 레이어에(셀렉터)」「무엇을 할지(패치)」의 쌍의 나열입니다. 셀렉터는 레이어 ID가 아니라 역할(도로·수역·라벨…)로 작성할 수 있습니다. OpenMapTiles·Shortbread·Mapbox Streets 스키마는 자동으로 구분하므로, 스타일마다 다른 레이어 ID를 조사할 필요가 없습니다.
createVectorStyle()이 반환하는 값을 어떤 *MapView에도 mapStyle로 전달합니다. React에서는 style이 요소 자신의 CSS이므로 이름은 mapStyle입니다(Android·iOS에서는 style).
rasteriser에 VectorTileRasteriser래스터라이저를 전달하지 않고 벡터 비지원 지도에 전달하면, 아무것도 그리지 않고 조용히 있는 것이 아니라 진단에 「이 스타일은 사용할 수 없습니다」라고 표시합니다.
02 · 설치
npm install @mapconductor/js-sdk-core @mapconductor/js-vectorstyle
벡터 비지원 지도에서도 사용하려면 래스터라이저가 들어 있는 react-vectortile도 설치합니다(벡터 타일 레이어의 Service Worker 준비도 필요합니다).
npm install @mapconductor/react-vectortile
ESM 전용입니다. 규칙의 컴파일러는 wasm(약 190 KB)이며, import.meta.url 기준 상대 경로로 읽어 들입니다. Vite라면 그대로 동작합니다. 다른 위치에서 배포할 때는 wasmUrl로 지정합니다.
03 · 기본 사용법
document를 생략하면, 지도가 현재 그리고 있는 스타일('currentDesign')을 조정합니다. 아래 예시는 MapLibre의 기본 디자인을 도로만 보이는 흑백 지도로 만듭니다.
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로 전체를 정하고, 역할별로 덮어쓰는 것이 기본입니다.
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 });
});*와 ?를 사용할 수 있습니다.규칙을 JSON으로 보관
규칙은 JSON 문서이기도 합니다. 서버에서 배포하거나, 앱의 버전을 넘나들며 저장할 때는 이 형태로 보관하고 parseStyleRules()로 읽어들입니다. 같은 문서를 Android・iOS에서도 읽을 수 있습니다.
{
"schemaVersion": 1,
"rules": [
{ "selector": "all", "patch": { "colorFilter": { "darken": 0.55 } } },
{ "selector": { "role": "water" }, "patch": { "color": "rgb(10,28,43)" } }
]
}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 디자인으로 하여 숨겨둡니다.
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 등으로 하나를 계속 유지하세요.06 · 주요 옵션
{ url, headers? }・{ text }・'currentDesign'.NO_STYLE_RULES이면 원본 그대로.'reload'이면 조정된 문서를 통째로 넘긴다(올바르지만 무겁다).진단은 *MapView의 onStyleDiagnostics로도 받을 수 있습니다. 생략하면 콘솔에 출력됩니다. "아무것도 적중하지 못한 규칙"은 겉모습만으로는 "거의 잘 동작한다"고밖에 알 수 없으므로, 개발하는 동안에는 눈에 보이는 곳에 출력해 두는 것을 권장합니다.