เลเยอร์เวกเตอร์ไทล์
แพ็กเกจที่วาดเวกเตอร์สไตล์รูปแบบ 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 จะถูกติดตั้งมาด้วยกันในฐานะ dependency แพ็กเกจนี้รองรับเฉพาะ ESM
วาง Service Worker สำหรับไทล์
ไทล์จะถูกส่งมอบจาก /tile-sw.js ข้อกำหนดเหมือนกับฮีตแมป กรุณาคัดลอกไฟล์ที่อยู่ใน @mapconductor/js-sdk-core ไปยังไดเรกทอรี public ของแอป
{
"scripts": {
"postinstall": "cp node_modules/@mapconductor/js-sdk-core/dist/tile-sw.js public/tile-sw.js"
}
}ใน production build ของ Vite จำเป็นต้องตั้งค่าให้ output worker เป็น ES module (ไม่จำเป็นบน dev server)
import { defineConfig } from 'vite';
export default defineConfig({
worker: { format: 'es' },
});localhost ใช้ HTTP ตามเดิมได้ แต่เมื่อเปิดจากอุปกรณ์อื่นใน LAN จะต้องใช้ HTTPS03 · วิธีใช้พื้นฐาน
วางไว้ใน *MapView ใดก็ได้ คุณสามารถส่ง style เป็น URL ของ style.json, เป็นสตริง หรือเป็นอ็อบเจกต์ที่แยกวิเคราะห์แล้วก็ได้ ตัวอย่างด้านล่างซ่อนแผนที่ของ 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 に ส่งกฎที่เขียนตามหัวข้อ การปรับสไตล์ของแผนที่ ไปยัง 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 จะไม่แปลงเป็นแรสเตอร์ แต่ส่งสไตล์ตรงไปที่แผนที่เพื่อแทนที่ดีไซน์ของแผนที่ ทั้งสามนี้วาดเวกเตอร์สไตล์ได้เอง จึงเร็วกว่าและสวยกว่า ในกรณีนี้ 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 ของ Mapbox และเลเยอร์บางชนิด จะแสดงใน onDiagnostics*MapView จะไม่ทำงานนอกแผนที่