벡터 타일 레이어
MapLibre 형식의 벡터 스타일(style.json)을 브라우저 안에서 래스터 타일로 그려, 어떤 지도 프로바이더에도 겹쳐 쓸 수 있게 하는 패키지입니다. Google Maps·MapKit·HERE·ArcGIS·Cesium처럼 벡터 스타일을 스스로 읽지 못하는 지도에서도 같은 모양으로 표시됩니다.
01 · 개요
렌더링은 Rust로 작성한 렌더러를 wasm으로 만든 것으로, Web Worker 안에서 동작합니다. 그린 타일은 SDK의 로컬 타일 서버(Service Worker)에서 제공되며, 지도에는 일반적인 RasterLayer로 올라갑니다. 지도 입장에서 보면 그저 래스터 레이어일 뿐입니다. 그래서 프로바이더를 가리지 않습니다.
레이어는 2장으로 나누어 올립니다. 채우기·선·원의 '지면'과, 그 위의 투명한 '라벨'입니다. 폰트가 도착했을 때 다시 그리는 것은 라벨 쪽뿐이므로, 글자가 나타나는 순간 지도가 한 번 사라지는 일이 발생하지 않습니다. 스타일의 출처(OpenStreetMap 등)의 저작권 표시도 자동으로 붙습니다.
02 · 설치
npm install @mapconductor/js-sdk-core @mapconductor/js-sdk-react \
@mapconductor/react-vectortile@mapconductor/js-vectorstyle도 의존성으로 함께 설치됩니다. 패키지는 ESM 전용입니다.
타일용 Service Worker 배치하기
타일은 /tile-sw.js에서 제공됩니다. 히트맵과 같은 요건입니다. @mapconductor/js-sdk-core에 들어 있는 파일을 앱의 공개 디렉터리로 복사하세요.
{
"scripts": {
"postinstall": "cp node_modules/@mapconductor/js-sdk-core/dist/tile-sw.js public/tile-sw.js"
}
}Vite의 프로덕션 빌드에서는 worker를 ES 모듈로 출력하는 설정이 필요합니다(dev 서버에서는 필요하지 않습니다).
import { defineConfig } from 'vite';
export default defineConfig({
worker: { format: 'es' },
});localhost라면 HTTP인 채로 괜찮지만, LAN 안의 다른 기기에서 열 때는 HTTPS가 필요합니다.03 · 기본 사용법
어떤 *MapView 안에도 배치할 수 있습니다. style에는 style.json의 URL, 해당 문자열, 파싱된 객체 중 무엇이든 전달할 수 있습니다. 아래 예는 Google Maps 자체 지도를 지우고(GoogleMapDesign.None), 그 위에 벡터 스타일을 그립니다.
import { createGeoPoint, createMapCameraPosition } from '@mapconductor/js-sdk-core';
import { GoogleMapDesign, GoogleMapView2D, useGoogleMapViewState } from '@mapconductor/react-for-googlemaps';
import { VectorTileLayer } from '@mapconductor/react-vectortile';
const TOKYO = createGeoPoint({ latitude: 35.6812, longitude: 139.7671 });
const STYLE_URL = 'https://tiles.versatiles.org/assets/styles/colorful/style.json';
export function VectorTileMap() {
const state = useGoogleMapViewState({
apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
mapDesignType: GoogleMapDesign.None,
cameraPosition: createMapCameraPosition({ position: TOKYO, zoom: 12 }),
});
return (
<GoogleMapView2D state={state} style={{ height: 480 }}>
<VectorTileLayer style={STYLE_URL} onDiagnostics={(messages) => console.warn(messages)} />
</GoogleMapView2D>
);
}style은 내용으로 비교합니다. 같은 내용이면 매번 새 객체를 만들어 전달해도 다시 그리지 않습니다.
04 · 모양 바꾸기
rules에 지도 스타일 바꾸기에서 작성하는 규칙을 전달하면, 색을 바꾸거나 레이어를 숨기는 등의 조정을 적용한 상태로 그립니다. 숨긴 역할(건물·라벨 등)은 애초에 그려지지 않습니다.
import { useMemo } from 'react';
import { buildStyleRules, LayerRole } from '@mapconductor/js-vectorstyle';
import { VectorTileLayer } from '@mapconductor/react-vectortile';
const rules = useMemo(
() => buildStyleRules((r) => {
r.role(LayerRole.building, { visible: false });
r.role(LayerRole.water, { colorFilter: { mix: { color: '#3a7ca5', amount: 0.6 } } });
r.role(LayerRole.label, { opacity: 0.6 });
}),
[],
);
<VectorTileLayer style={STYLE_URL} rules={rules} />규칙이나 스타일을 바꾸면 메모리에 있는 벡터 타일을 다시 그리기만 하고, 네트워크로 가져가지 않습니다. 형태는 변하지 않고 칠하는 방법만 바뀌었기 때문입니다. 슬라이더로 색을 움직이는 식의 사용이라도 통신은 늘지 않습니다. rules를 생략하면 규칙 컴파일러(wasm)는 로드되지 않습니다.
05 · 베이스맵으로 사용하기
asBasemap을 붙이면 MapLibre·Mapbox·MapTiler에서는 래스터로 만들지 않고, 스타일을 그대로 지도에 전달하여 지도 디자인과 교체합니다. 이 3개는 직접 벡터 스타일을 그릴 수 있으므로 그쪽이 더 빠르고 깔끔합니다. 이때 opacity는 적용되지 않습니다.
import { MapLibreMapView2D, useMapLibreViewState } from '@mapconductor/react-for-maplibre';
import { VectorTileLayer } from '@mapconductor/react-vectortile';
<MapLibreMapView2D state={state}>
<VectorTileLayer style={STYLE_URL} rules={rules} asBasemap />
</MapLibreMapView2D>그 외 프로바이더에서는 asBasemap은 아무것도 바꾸지 않습니다. 프로바이더 자체 지도는 앱 쪽에서 None 디자인으로 하여 지우십시오.
06 · 주요 프로퍼티
키가 필요한 타일 사용하기
<VectorTileLayer
style="https://tiles.example.com/styles/basic/style.json"
headers={{ Authorization: `Bearer ${token}` }}
/>07 · 현재의 제한
imports와 일부 레이어 타입은 그리지 않습니다. onDiagnostics에 표시됩니다.*MapView 안에 넣어야 합니다. 지도 밖에서는 동작하지 않습니다.