コンテンツにスキップ

MapViewComponent

MapConductor は、アプリケーションで地図を表示するための基盤となる、地図SDK固有の地図ビューコンポーネントを提供します。各地図SDKには独自の実装がありますが、一貫した API インターフェースを維持しています。

MapConductor は複数の地図SDKをサポートしており、それぞれに専用のコンポーネントがあります。 地図上には通常、複数のオブジェクト(マーカーやポリラインなど)が配置されるため、個々のオブジェクトにイベントコールバックを設定するのではなく、 地図SDK固有のコンポーネントにイベントコールバックを設定します。

各地図SDK固有の特殊なイベントコールバックについては、v1.1.2 ではまだサポートされていません。

GoogleMapView(
state: GoogleMapViewStateImpl,
modifier: Modifier = Modifier,
markerRenderingStrategy: MarkerRenderingStrategy<GoogleMapActualMarker>? = null,
onMapLoaded: OnMapLoadedHandler? = null,
onMapClick: OnMapEventHandler? = null,
onCameraMoveStart: OnCameraMoveHandler? = null,
onCameraMove: OnCameraMoveHandler? = null,
onCameraMoveEnd: OnCameraMoveHandler? = null,
onMarkerClick: OnMarkerEventHandler? = null,
onMarkerDragStart: OnMarkerEventHandler? = null,
onMarkerDrag: OnMarkerEventHandler? = null,
onMarkerDragEnd: OnMarkerEventHandler? = null,
onMarkerAnimateStart: OnMarkerEventHandler? = null,
onMarkerAnimateEnd: OnMarkerEventHandler? = null,
onPolylineClick: OnPolylineEventHandler? = null,
onCircleClick: OnCircleEventHandler? = null,
onPolygonClick: OnPolygonEventHandler? = null,
onGroundImageClick: OnGroundImageEventHandler? = null,
content: (@Composable MapViewScope.() -> Unit)? = null
)

すべての地図ビューコンポーネントは以下のパラメータを共有しています:

  • modifier: スタイリングとレイアウトのための Compose modifier
  • state: 地図SDK固有の地図ビュー状態実装
  • content: 地図オーバーレイ(マーカー、円など)を含む Composable コンテンツ
  • onMapLoaded: 地図の読み込みが完了したときに呼び出されます
  • onMapClick: ユーザーが地図をタップしたときに呼び出されます
  • カメライベント: onCameraMoveStartonCameraMoveonCameraMoveEnd
  • マーカーイベント: onMarkerClickonMarkerDragStartonMarkerDragonMarkerDragEndonMarkerAnimateStartonMarkerAnimateEnd
  • オーバーレイイベント: onCircleClickonPolylineClickonPolygonClickonGroundImageClick
  • markerRenderingStrategy: パフォーマンス最適化のためのカスタムマーカーレンダリング戦略
@Composable
fun GoogleMapsExample() {
val mapViewState = rememberGoogleMapViewState()
GoogleMapView(
state = mapViewState,
onMapClick = { geoPoint ->
println("Map clicked at: ${geoPoint.latitude}, ${geoPoint.longitude}")
},
onMarkerClick = { markerState ->
println("Marker clicked: ${markerState.extra}")
}
) {
Marker(
position = GeoPointImpl.fromLatLong(37.7749, -122.4194),
icon = DefaultIcon(label = "SF"),
extra = "San Francisco"
)
Circle(
center = GeoPointImpl.fromLatLong(37.7749, -122.4194),
radiusMeters = 1000.0,
strokeColor = Color.Blue,
fillColor = Color.Blue.copy(alpha = 0.3f)
)
}
}

各地図SDKには特定のコンポーネントが必要ですが、地図SDKに依存しないコンテンツを作成できます:

@Composable
fun MapContent() {
Marker(
position = GeoPointImpl.fromLatLong(37.7749, -122.4194),
icon = DefaultIcon(label = "Point"),
extra = "Common marker"
)
Circle(
center = GeoPointImpl.fromLatLong(37.7749, -122.4194),
radiusMeters = 500.0,
strokeColor = Color.Green,
fillColor = Color.Green.copy(alpha = 0.2f)
)
}
@Composable
fun GoogleMapsScreen() {
val state = rememberGoogleMapViewState()
GoogleMapView(state = state) {
MapContent() // 再利用可能なコンテンツ
}
}
@Composable
fun MapboxScreen() {
val state = remember { MapboxViewStateImpl() }
MapboxMapView(state = state) {
MapContent() // 同じコンテンツ、異なる地図SDK
}
}
@Composable
fun AdvancedMapExample() {
val center = GeoPointImpl.fromLatLong(37.7749, -122.4194)
val mapViewState = rememberGoogleMapViewState(
cameraPosition = MapCameraPositionImpl(
position = center,
zoom = 13.0,
),
)
// Recompositionでマーカーを再生成しないように、rememberで囲む
val markerState1 by remember { mutableStateOf(MarkerState(
id = "marker1",
position = GeoPointImpl.fromLatLong(37.7749, -122.4194),
icon = DefaultIcon(
fillColor = Color.Blue,
label = "1"
),
// marker1 はドラッグできるようにする
draggable = true,
)) }
val markerState2 by remember { mutableStateOf( MarkerState(
id = "marker2",
position = GeoPointImpl.fromLatLong(37.7849, -122.4094),
icon = DefaultIcon(
fillColor = Color.Red,
label = "2"
),
)) }
// 選択されたマーカーを保持
var selectedMarker by remember { mutableStateOf<MarkerState?>(null) }
GoogleMapView(
state = mapViewState,
onMapLoaded = {
println("Map loaded and ready")
},
onMapClick = { geoPoint ->
selectedMarker = null // 地図クリックで選択解除
},
onMarkerClick = { markerState ->
selectedMarker = markerState // クリックされたマーカーを保持する
},
onMarkerDragStart = { markerState ->
println("Started dragging marker: ${markerState.id}")
},
onMarkerDrag = { markerState ->
println("Dragging marker to: ${markerState.position}")
},
onMarkerDragEnd = { markerState ->
println("Finished dragging marker: ${markerState.id}")
}
) {
// インタラクティブなマーカーを持つ地図コンテンツ
Marker(markerState1)
Marker(markerState2)
// 選択されたマーカーの情報を表示
selectedMarker?.let { marker ->
val text = GeoPointImpl.from(marker.position).toUrlValue(6)
// InfoBubbleは関連付けられたマーカーのpositionを自動で追尾する
InfoBubble(
marker = marker,
) {
Text(text)
}
}
}
}

API は全地図SDKで一貫していますが、以下の点で違いがあります:

  • GroundImage: 現在 Google Maps と ArcGIS でサポートされています
  • マーカーアニメーション: Google Maps と Mapbox で利用可能
  • カスタムスタイリング: 各地図SDKには異なる地図スタイルオプションがあります
  • Google Maps: 一般的な使用に優れており、優れたマーカーパフォーマンス
  • Mapbox: カスタムスタイリングと大規模データセットに最適
  • HERE Maps: ロケーションサービス統合に最適化
  • ArcGIS: GIS およびエンタープライズアプリケーションに最適

各地図SDKには、API キー、パーミッション、プラットフォームセットアップに関して異なる要件がある場合があります。地図SDK固有のセットアップについては、初期化ドキュメントを参照してください。

  1. 適切な地図SDKを選択: アプリの特定のニーズに基づいて選択してください(スタイリング、パフォーマンス、機能)
  2. 一貫した状態管理: 地図SDKに関係なく、同じ状態パターンを使用してください
  3. 再利用可能なコンテンツ: 可能な限り地図SDKに依存しない Composable コンテンツを作成してください
  4. イベント処理: より良いユーザーエクスペリエンスのために包括的なイベント処理を実装してください
  5. エラー処理: 常に初期化の失敗を処理し、フォールバック UI を提供してください
  6. パフォーマンス: 大量のマーカーに対してはカスタムレンダリング戦略の使用を検討してください
  7. テスト: 互換性を確保するために、複数の地図SDKでアプリケーションをテストしてください