สลับผู้ให้บริการ
สิ่งที่แตกต่างกันไปในแต่ละผู้ให้บริการมีเพียง 3 อย่างคือโมดูลที่ต้องพึ่งพา ประเภทของมุมมองแผนที่ และประเภทของออบเจกต์สถานะ วิธีเขียนมาร์กเกอร์ รูปร่าง การดำเนินการกล้อง และเหตุการณ์ไม่เปลี่ยนแปลง คุณยังสามารถจัดเรียงผู้ให้บริการหลายรายบนหน้าจอเดียวกันและสลับได้ในรันไทม์
01 · สิ่งที่เปลี่ยนแปลงและสิ่งที่ยังคงเหมือนเดิม
- โมดูลที่ต้องพึ่งพา (for-maplibre → for-googlemaps ฯลฯ)
- ประเภทมุมมองแผนที่ (MapLibreMapView → GoogleMapView)
- ประเภทของออบเจกต์สถานะและฟังก์ชันสร้าง
- ค่าคงที่ของการออกแบบที่ส่งไปยัง mapDesignType
- วิธีรับคีย์ API และขั้นตอนการเริ่มต้น
- GeoPoint · GeoRectBounds · MapCameraPosition
- MarkerState · PolylineState · PolygonState · CircleState …
- moveCameraTo() · fitBounds() · ตัวจัดการเหตุการณ์
- การคำนวณทางภูมิศาสตร์ (ระยะทาง ทิศทาง พื้นที่)
- เลเยอร์ขยาย (การจัดกลุ่ม แผนที่ความร้อน GeoJSON)
ประเภทของออบเจกต์สถานะถูกแยกสำหรับแต่ละผู้ให้บริการ แต่จะใช้งานอินเทอร์เฟซส่วนกลาง (Android: MapViewStateInterface, iOS: MapViewStateProtocol, React: MapViewStateInterface) การดำเนินการกล้องและการสลับดีไซน์สามารถเขียนผ่านอินเทอร์เฟซส่วนกลางนี้ได้





02 · ประเภทตามผู้ให้บริการ
รายการมุมมองแผนที่และออบเจกต์สถานะที่ผู้ให้บริการแต่ละรายเปิดเผย เนื่องจากเหตุผลทางประวัติศาสตร์ มีบางจุดที่ชื่อไม่สอดคล้องกันทั้งหมด ดังนั้นชื่อที่ export จริงจึงถูกแสดงตามที่เป็นอยู่
rememberGoogleMapViewState
GoogleMapViewState
GoogleMapViewState
useGoogleMapViewState
rememberMapLibreMapViewState
MapLibreViewState
MapLibreViewState
useMapLibreViewState
rememberMapboxMapViewState
MapboxViewState
MapboxViewState
useMapboxViewState
rememberHereMapViewState
HereViewState
HereMapViewState
useHereViewState
rememberArcGISMapViewState
ArcGISMapViewState
ArcGISMapViewState
useArcGISViewState
rememberMapTilerMapViewState
MapTilerViewState
MapTilerViewState
useMapTilerViewState
rememberTomTomMapViewState
TomTomMapViewState
TomTomMapViewState
useTomTomViewState
rememberLongdoMapViewState
LongdoViewState
LongdoViewState
useLongdoViewState
MapKitViewState
useMapKitViewState
useLeafletMapViewState
useOpenLayersMapViewState
useAzureMapsViewState
useCesiumMapViewState
"/ 2D" หมายความว่ามีสองมุมมองคือมุมมอง 3D และมุมมอง 2D ทั้งสองแชร์ออบเจกต์สถานะเดียวกัน และในมุมมอง 2D tilt จะเป็น 0 เสมอ
03 · วิธีเขียนการสลับ
เมื่อต้องการสลับในรันไทม์ ให้เก็บออบเจกต์สถานะไว้หนึ่งตัวสำหรับแต่ละผู้ให้บริการ และแยกเฉพาะมุมมองที่จะแสดง คำอธิบายโอเวอร์เลย์สามารถวางไว้นอกการแยกสาขาได้ แอปตัวอย่างอยู่ในรูปแบบนี้
@Composable
fun MapViewContainer(
modifier: Modifier = Modifier,
state: MapViewStateInterface<*>? = null,
content: (@Composable MapViewScope.() -> Unit)? = null,
) {
when (state) {
is GoogleMapViewState -> GoogleMapView(modifier, state, content = content)
is MapLibreViewState -> MapLibreMapView(modifier, state, content = content)
is MapboxViewState -> MapboxMapView(modifier, state, content = content)
is HereViewState -> HereMapView(modifier, state, content = content)
else -> { /* not selected */ }
}
}
// ฝั่งเรียกใช้เขียนเฉพาะโอเวอร์เลย์
MapViewContainer(state = selectedState) {
Markers(markerStates)
}@StateObject private var googleState = GoogleMapViewState(cameraPosition: initial)
@StateObject private var mapLibreState = MapLibreViewState(cameraPosition: initial)
// ผ่านอินเทอร์เฟซร่วม การสั่งกล้องเขียนได้โดยไม่ต้องแยกกรณี
private var activeState: any MapViewStateProtocol {
provider == .googleMaps ? googleState : mapLibreState
}
@ViewBuilder
private var mapView: some View {
switch provider {
case .googleMaps:
GoogleMapView(state: googleState, sdkInitialize: {
GMSServices.provideAPIKey(apiKey)
}) { Marker(state: markerState) }
case .mapLibre:
MapLibreMapView(state: mapLibreState) { Marker(state: markerState) }
}
}// เรียกฮุกแบบตายตัวต่อคอมโพเนนต์ แล้วสลับเฉพาะวิว
const maplibre = useMapLibreViewState({ id: 'maplibre', cameraPosition: INIT });
const google = useGoogleMapViewState({ id: 'google', cameraPosition: INIT });
switch (provider) {
case 'maplibre':
return <MapLibreMapView2D state={maplibre}>{children}</MapLibreMapView2D>;
case 'google-maps':
return <GoogleMapView2D state={google}>{children}</GoogleMapView2D>;
}ใน React ไม่สามารถเปลี่ยนลำดับการเรียก hook ได้ ดังนั้นการแยกมุมมองตามผู้ให้บริการออกเป็นคอมโพเนนต์แยกต่างหากและเรียก hook ภายในคอมโพเนนต์นั้นจึงปลอดภัย ไดเร็กทอรี providers/ ของแอปตัวอย่างมีโครงสร้างนี้
// One state per provider
val maplibre = rememberMapLibreMapViewState(
mapDesign = MapLibreDesign.OsmBrightJa,
cameraPosition = MapCameraPosition(
position = GeoPoint.fromLatLong(35.6812, 139.7671),
zoom = 12.0,
),
)
val googlemaps = rememberGoogleMapViewState(
cameraPosition = MapCameraPosition(
position = GeoPoint.fromLatLong(35.6812, 139.7671),
zoom = 12.0,
),
)
var useMapLibre by remember { mutableStateOf(true) }
// The overlays are declared outside the branch, so swapping does not touch them
val overlays: @Composable MapViewScope.() -> Unit = {
Marker(markerState)
Polyline(routeState)
}
// Hand the camera you were just looking at to the side you are switching to
LaunchedEffect(useMapLibre) {
if (useMapLibre) {
maplibre.moveCameraTo(googlemaps.cameraPosition)
} else {
googlemaps.moveCameraTo(maplibre.cameraPosition)
}
}
if (useMapLibre) {
MapLibreMapView(state = maplibre, content = overlays)
} else {
GoogleMapView(state = googlemaps, content = overlays)
}04 · การจัดการความแตกต่างของผู้ให้บริการ
ไม่ใช่ทุก SDK แผนที่ที่จะมีฟีเจอร์เหมือนกัน MapConductor จะเติมเต็มส่วนที่ต่างได้ และจัดเตรียมการนำเสนอทางเลือกสำหรับส่วนที่เติมเต็มไม่ได้
หากไม่มีฟังก์ชันแบบเนทีฟ SDK จะแสดงผลเป็นไทล์แรสเตอร์เอง ซึ่งรวมถึงรูในรูปหลายเหลี่ยมและการวาดมาร์เกอร์จำนวนมาก โค้ดฝั่งที่เรียกใช้ไม่เปลี่ยนแปลง
สำหรับองค์ประกอบที่ผู้ให้บริการนั้นไม่สามารถจัดการได้ ไดรเวอร์จะไม่มีเรนเดอร์ที่รองรับ การระบุว่าใช้งานได้หรือไม่ทำได้ตั้งแต่เวลาคอมไพล์ หรือด้วยประเภทของออบเจกต์สถานะ
หากคุณต้องการฟังก์ชันเฉพาะของผู้ให้บริการนั้นอย่างยิ่ง คุณสามารถดึงอินสแตนซ์แผนที่เนทีฟจาก `MapViewHolder` และเรียกใช้โดยตรงได้
คีย์และการเริ่มต้นแยกตามผู้ให้บริการ
`MapConductor` ไม่รับผิดชอบคีย์ API โดยจะส่งผ่านไปตามรูปแบบที่ SDK แผนที่แต่ละตัวต้องการ (ไฟล์ Manifest ของ Android, `sdkInitialize` บน iOS, ออบเจกต์การตั้งค่าบนเว็บ) มีผู้ให้บริการบางรายอย่าง `MapLibre`, `Leaflet` และ `OpenLayers` ที่ไม่ต้องการคีย์ ในกรณีนั้นจะระบุเพียงแหล่งที่มาของไทล์เท่านั้น