문서 / 지도 뷰 / 지도 스타일 바꾸기

지도 스타일 바꾸기

지도의 벡터 스타일에 「도로를 흰색으로」「라벨 숨기기」「수역을 어둡게」 같은 조정을 규칙으로서 선언적으로 적용하는 패키지입니다. 같은 규칙을 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 등으로 하나를 계속 유지하세요.

06 · 주요 옵션

옵션
기본값
설명
document
'currentDesign'
조정할 스타일. { url, headers? }・{ text }・'currentDesign'.
rules
—
적용할 규칙. NO_STYLE_RULES이면 원본 그대로.
rasteriser
—
벡터를 지원하지 않는 지도에 그리기 위한 것.
onUnsupported
'report'
지도가 차분을 받아들이지 않을 때. 'reload'이면 조정된 문서를 통째로 넘긴다(올바르지만 무겁다).
onDiagnostics
—
적중한 레이어의 수, 아무것도 적중하지 못한 규칙, 지도가 거부한 조정.
wasmUrl
—
컴파일러의 wasm 위치.

진단은 *MapView의 onStyleDiagnostics로도 받을 수 있습니다. 생략하면 콘솔에 출력됩니다. "아무것도 적중하지 못한 규칙"은 겉모습만으로는 "거의 잘 동작한다"고밖에 알 수 없으므로, 개발하는 동안에는 눈에 보이는 곳에 출력해 두는 것을 권장합니다.

관련 페이지