เปลี่ยนสไตล์แผนที่
แพ็กเกจที่ใช้ปรับแต่งเวกเตอร์สไตล์ของแผนที่ เช่น "ทำให้ถนนเป็นสีขาว" "ซ่อนป้ายชื่อ" "ทำให้พื้นที่น้ำมืดลง" โดยประกาศเป็นกฎเชิงประกาศ (declarative) กฎชุดเดียวกันใช้ได้ทันทีบน Android และ iOS ด้วย
01 · ภาพรวม
กฎคือลำดับของคู่ "เลเยอร์ใด (ตัวเลือก selector)" และ "ทำอะไร (แพตช์ patch)" ตัวเลือกสามารถเขียนตามบทบาท (ถนน พื้นที่น้ำ ป้ายชื่อ…) แทนที่จะใช้ ID ของเลเยอร์ สคีมาของ OpenMapTiles, Shortbread และ Mapbox Streets ถูกแยกแยะโดยอัตโนมัติ จึงไม่ต้องค้นหา ID เลเยอร์ที่ต่างกันของแต่ละสไตล์
ส่งค่าที่ createVectorStyle() คืนไปเป็น mapStyle ให้กับ *MapView ใดก็ได้ ใน React ชื่อเป็น mapStyle เพราะ style เป็น CSS ของตัวองค์ประกอบเอง (บน Android และ iOS ใช้ style)
VectorTileRasteriser ให้กับ rasteriserหากส่งไปยังแผนที่ที่ไม่รองรับเวกเตอร์โดยไม่ส่งแรสเตอร์ไรเซอร์ ระบบจะไม่วาดอะไรเงียบ ๆ แต่จะแสดงข้อวินิจฉัยว่า "สไตล์นี้ใช้ไม่ได้"
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)}
/>
);
}เมื่อใช้สไตล์ของตัวเอง ให้ส่ง { url } หรือ { text } ไปที่ document
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' จะส่งเอกสารที่ปรับแล้วทั้งชุด (ถูกต้องแต่หนัก)สามารถรับข้อมูลวินิจฉัยได้ทาง onStyleDiagnostics ของ *MapView ด้วย หากละไว้จะแสดงในคอนโซล "กฎที่ไม่ถูกจับคู่เลย" นั้นจากหน้าตาภายนอกแยกให้ออกว่า "เกือบจะทำงาน" เท่านั้น จึงแนะนำให้แสดงไว้ในที่ที่มองเห็นระหว่างการพัฒนา