マーカー
マーカーは状態オブジェクトを1つ作って地図ビューに置くだけです。描画は SDK 内部のレンダリングエンジンが担当し、件数に応じて描き方を自動で切り替えます。既定では 2,000個までが各地図SDKの標準マーカー、それを超えるとラスタータイルです。この基準値は地図ビューにタイル描画オプションを渡して変更できます。
01 · マーカーの状態
MarkerState が1つのマーカーを表します。位置・アイコン・イベント・任意の付随データを持ち、プロパティを書き換えれば即座に反映されます。プロバイダごとの型はありません。
val marker =
MarkerState(
position = GeoPoint.fromLatLong(21.3069, -157.8583),
icon = DefaultMarkerIcon(fillColor = Color.Red, label = "A"),
extra = postOffice,
onClick = { clicked -> viewModel.onMarkerClick(clicked) },
)
// 位置やアイコンは後から書き換えるだけで再描画される
marker.position = nextPointlet marker = MarkerState(
position: GeoPoint.fromLatLong(latitude: 21.3069, longitude: -157.8583),
icon: DefaultMarkerIcon(fillColor: .red, label: "A"),
extra: postOffice,
onClick: { clicked in viewModel.onMarkerClick(clicked) }
)
content.markers = markerStates.map { Marker(state: $0) }const marker = createMarkerState({
id: 'post-office-1',
position: createGeoPoint({ latitude: 21.3069, longitude: -157.8583 }),
icon: new ColorDefaultIcon({ fillColor: '#e74c3c', label: 'A' }),
extra: postOffice,
onClick: setSelected,
});
<Markers states={markerStates} />02 · アイコン
既定のピンに色やラベルを載せるだけの指定から、画像・キャンバス、吹き出し型アイコンまで用意しています。どのアイコンもプロバイダをまたいで同じ見た目になります。
ColorDefaultIcon
ImageIcon / ImageDefaultIcon
CircleIcon / FlagIcon
RoundInfoBubbleIcon
RightTailInfoBubbleIcon
scale · anchor · debug
03 · 内部のレンダリングエンジン
マーカーの描画は SDK 内部のレンダリングエンジンに任せています。件数が少ないうちは各地図SDKの標準マーカーをそのまま使い、ネイティブのタップ判定やアニメーションをそのまま活かします。
マーカーが 2,000個を超えると、エンジンは描き方を切り替えます。マーカー群をタイル画像としてレンダリングし、ラスターレイヤーとして重ねることで、ネイティブSDKへの1件ずつの追加・更新コストをなくします。アプリ側のコードは何も変わりません。
標準マーカーで描画
ラスタータイルで描画

// 既定で有効。地図ビューに渡して基準値を変える(Android の引数名は markerTiling)
val markerTiling =
MarkerTilingOptions.Default.copy(
minMarkerCount = 500, // 500件からタイル描画に切り替える
iconScaleCallback = { _, zoom ->
if (zoom > 10) 0.8 else if (zoom > 5) 0.5 else 0.2
},
)
GoogleMapView(state = mapViewState, markerTiling = markerTiling) { /* markers */ }
// 常に標準マーカーで描かせたいときは無効化する
val plain = MarkerTilingOptions.Disabledvar content = MapViewContent()
content.markerTilingOptions = MarkerTilingOptions(
minMarkerCount: 500, // 500件からタイル描画に切り替える
iconScaleCallback: { _, zoom in
PostOfficeViewModel.iconScale(zoom: zoom)
}
)
content.markers = markers.map { Marker(state: $0) }const MARKER_TILING_OPTIONS: MarkerTilingOptions = {
...MarkerTilingOptions.Default,
minMarkerCount: 500, // 500件からタイル描画に切り替える
iconScaleCallback: (_state, zoom) => (zoom > 10 ? 0.8 : zoom > 5 ? 0.5 : 0.2),
};
<PostOfficeMapProvider markerTilingOptions={MARKER_TILING_OPTIONS}>
<Markers states={markerStates} />
</PostOfficeMapProvider>空間インデックスで探す
大量のマーカーを持つときは六角セルの空間インデックスを使い、表示範囲内のマーカー抽出やタップ判定を件数に依存しない速さで行います。少数のときは総当たりのほうが速いので、そちらを使います。
クラスタリングは別モジュール
近接マーカーをまとめて1つのバッジにする「マーカーを大量に置く(クラスタリング)」は追加モジュールです。ここで説明したタイル描画は標準機能で、クラスタリングとは独立して働きます。
04 · アニメーション
簡易的なアニメーションを標準で用意しています。生成時に指定するか、あとから animate() を呼ぶだけです。開始・終了はハンドラで受け取れます。
MarkerAnimation.Drop
MarkerAnimation.Bounce
// 生成時に指定するか、あとから animate() を呼ぶ
MarkerState(position = point, animation = MarkerAnimation.Bounce)
override fun onMarkerClick(clicked: MarkerState) {
clicked.animate(clicked.extra as? MarkerAnimation)
}if let animation = clicked.extra as? MarkerAnimation {
clicked.animate(animation)
}const marker = createMarkerState({
id: 'animated-marker',
position: HONOLULU,
animation,
onClick: state => state.animate(MarkerAnimation.Bounce),
});アニメーション中のマーカーは専用のオーバーレイで描画されるため、タイル描画に切り替わっている状態でも動きます。所要時間は SDK の設定で変更できます。