コンテンツにスキップ

MarkerState(マーカー状態)

MarkerState はマーカーの位置や見た目、インタラクション設定を管理するための状態クラスです。Compose らしいリアクティブな更新と、効率的な差分検知の仕組みを提供します。

MarkerState(
position: GeoPointInterface,
id: String? = null,
extra: Serializable? = null,
icon: MarkerIconInterface? = null,
animation: MarkerAnimation? = null,
clickable: Boolean = true,
draggable: Boolean = false,
onClick: OnMarkerEventHandler? = null,
onDragStart: OnMarkerEventHandler? = null,
onDrag: OnMarkerEventHandler? = null,
onDragEnd: OnMarkerEventHandler? = null,
onAnimateStart: OnMarkerEventHandler? = null,
onAnimateEnd: OnMarkerEventHandler? = null,
)

MarkerStateonClick / onDragStart / onDrag / onDragEnd / onAnimateStart / onAnimateEnd をコンストラクタで受け取り、各イベントを State 単位で処理できます。

  • id: String: マーカーの一意な ID(未指定の場合は自動生成)
  • position: GeoPointInterface: 現在のマーカー位置
  • extra: Serializable?: 追加情報など、任意の付帯データ
  • icon: MarkerIconInterface?: マーカーのアイコン(未指定の場合はデフォルトアイコン)
  • clickable: Boolean: マーカーがクリックイベントに反応するかどうか
  • draggable: Boolean: マーカーをユーザーがドラッグできるかどうか

インタラクション関連のプロパティ

Section titled “インタラクション関連のプロパティ”
  • onClick: (MarkerState) -> Unit: マーカーがクリックされたときに呼び出されるコールバック
  • onDragStart: (MarkerState) -> Unit: ドラッグ開始時に呼び出されるコールバック
  • onDrag: (MarkerState) -> Unit: ドラッグ中に継続的に呼び出されるコールバック
  • onDragEnd: (MarkerState) -> Unit: ドラッグ終了時に呼び出されるコールバック
  • onAnimateStart: (MarkerState) -> Unit: アニメーション開始時に呼び出されるコールバック
  • onAnimateEnd: (MarkerState) -> Unit: アニメーション終了時に呼び出されるコールバック
fun setAnimation(animation: MarkerAnimation?)
fun copy(
id: String? = this.id,
position: GeoPointInterface = this.position,
extra: Serializable? = this.extra,
icon: MarkerIconInterface? = this.icon,
clickable: Boolean? = this.clickable,
draggable: Boolean? = this.draggable,
onClick: OnMarkerEventHandler? = this.onClick,
onDragStart: OnMarkerEventHandler? = this.onDragStart,
onDrag: OnMarkerEventHandler? = this.onDrag,
onDragEnd: OnMarkerEventHandler? = this.onDragEnd,
onAnimateStart: OnMarkerEventHandler? = this.onAnimateStart,
onAnimateEnd: OnMarkerEventHandler? = this.onAnimateEnd
): MarkerState
fun asFlow(): Flow<MarkerFingerPrint>
fun fingerPrint(): MarkerFingerPrint

既存の状態を元に、一部プロパティだけを変えた新しい MarkerState を生成したり、差分検知のためのフィンガープリント(スナップショット)を生成したりできます。

val markerState = MarkerState(
position = GeoPoint.fromLatLong(37.7749, -122.4194),
extra = "サンフランシスコのマーカー"
)
MapView(state = mapViewState) {
Marker(markerState)
}

実行結果

val customMarkerState = MarkerState(
position = GeoPoint.fromLatLong(37.7749, -122.4194),
icon = DefaultIcon(
fillColor = Color.Blue,
label = "SF",
scale = 1.2f
),
clickable = true,
draggable = true,
extra = "ドラッグ可能なサンフランシスコのマーカー",
onClick = { markerState ->
println("クリックされたマーカー: ${markerState.extra}")
markerState.animate(MarkerAnimation.Bounce)
},
onDrag = { markerState ->
println("マーカーがドラッグされました: ${markerState.position}")
}
)
MapView(
state = mapViewState
) {
Marker(customMarkerState)
}

実行結果のログ

マーカーがドラッグされました: GeoPoint(latitude=37.781026576871554, longitude=-122.41839353250903, altitude=0.0)
マーカーがドラッグされました: GeoPoint(latitude=37.78035405874677, longitude=-122.41897685009974, altitude=0.0)
...
クリックされたマーカー: ドラッグ可能なサンフランシスコのマーカー
@Composable
fun DynamicMarkerExample() {
val colors = listOf(
Color.Red,
Color.Blue,
Color.Yellow,
Color.Green,
Color.Cyan,
Color.Magenta,
Color.White,
)
var markerState by remember {
mutableStateOf(
MarkerState(
position = GeoPoint.fromLatLong(37.7749, -122.4194),
icon = DefaultIcon(fillColor = Color.Red, label = "0"),
extra = "カウンター: 0"
)
)
}
var counter by remember { mutableStateOf(0) }
Column {
Button(
onClick = {
counter++
markerState = markerState.copy(
icon = DefaultIcon(
fillColor = colors[counter % colors.size],
label = counter.toString()
),
extra = "カウンター: $counter"
)
}
) {
Text("マーカーを更新 ($counter)")
}
MapView(state = mapViewState) {
Marker(markerState)
}
}
}

位置をアニメーションさせる MarkerState

Section titled “位置をアニメーションさせる MarkerState”
@Composable
fun AnimatedMarkerExample() {
val startPosition = GeoPoint.fromLatLong(37.775111, -122.419206)
val endPosition = GeoPoint.fromLatLong(37.780522, -122.412522)
var markerState by remember {
mutableStateOf(
MarkerState(
position = startPosition,
icon = DefaultIcon(fillColor = Color.Green, label = "移動中"),
extra = "アニメーションするマーカー"
)
)
}
LaunchedEffect(Unit) {
val path = (0 .. 10)
.map { it * 0.1 }
.map {
Spherical.sphericalInterpolate(
from = startPosition,
to = endPosition,
fraction = it,
)
}
var direction = 1;
var idx = 0
while (true) {
delay(1000)
for (i in 0..path.size - 2) {
idx += direction
markerState.position = path[idx]
println("$idx : ${GeoPoint.from(path[idx]).toUrlValue()}")
delay(50)
}
direction = direction * -1
}
}
val mapViewState =
rememberMapLibreMapViewState(
cameraPosition = MapCameraPosition(
position = GeoPoint.fromLatLong(37.7791, -122.4144),
zoom = 15.0,
),
mapDesign = MapLibreDesign.OsmBrightEn,
)
MapView(state = mapViewState) {
Marker(markerState)
}
}

実行結果