Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/android-for-maptiler.api
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ public final class com.mapconductor.maptiler.MapTilerMapViewHolder implements co
public java.lang.Object getMap();
}
public final class com.mapconductor.maptiler.MapTilerMapViewKt {
public static final void MapTilerMapView(com.mapconductor.maptiler.MapTilerViewState, androidx.compose.ui.Modifier, com.mapconductor.core.marker.MarkerTilingOptions, com.mapconductor.core.map.CameraRestriction, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapViewStateInterface<?>, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function3<? super com.mapconductor.compose.MapViewScope, ? super androidx.compose.runtime.Composer, ? super java.lang.Integer, kotlin.Unit>, androidx.compose.runtime.Composer, int, int, int);
public static final void MapTilerMapSurface(com.mapconductor.maptiler.MapTilerViewState, androidx.compose.ui.Modifier, com.mapconductor.core.marker.MarkerTilingOptions, com.mapconductor.core.map.CameraRestriction, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapViewStateInterface<?>, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.maptiler.MapTilerMapViewController, kotlin.Unit>, kotlin.jvm.functions.Function3<? super com.mapconductor.compose.MapViewScope, ? super androidx.compose.runtime.Composer, ? super java.lang.Integer, kotlin.Unit>, androidx.compose.runtime.Composer, int, int, int);
public static final void MapTilerMapView(com.mapconductor.maptiler.MapTilerViewState, androidx.compose.ui.Modifier, com.mapconductor.core.marker.MarkerTilingOptions, com.mapconductor.core.map.CameraRestriction, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapViewStateInterface<?>, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, com.mapconductor.core.map.MapViewStyle, kotlin.jvm.functions.Function1<? super java.util.List<java.lang.String>, kotlin.Unit>, kotlin.jvm.functions.Function3<? super com.mapconductor.compose.MapViewScope, ? super androidx.compose.runtime.Composer, ? super java.lang.Integer, kotlin.Unit>, androidx.compose.runtime.Composer, int, int, int);
public static final void MapTilerMapSurface(com.mapconductor.maptiler.MapTilerViewState, androidx.compose.ui.Modifier, com.mapconductor.core.marker.MarkerTilingOptions, com.mapconductor.core.map.CameraRestriction, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapViewStateInterface<?>, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.features.GeoPoint, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.core.map.MapCameraPosition, kotlin.Unit>, kotlin.jvm.functions.Function1<? super com.mapconductor.maptiler.MapTilerMapViewController, kotlin.Unit>, com.mapconductor.core.map.MapViewStyle, kotlin.jvm.functions.Function1<? super java.util.List<java.lang.String>, kotlin.Unit>, kotlin.jvm.functions.Function3<? super com.mapconductor.compose.MapViewScope, ? super androidx.compose.runtime.Composer, ? super java.lang.Integer, kotlin.Unit>, androidx.compose.runtime.Composer, int, int, int);
}
public final class com.mapconductor.maptiler.MapTilerMapViewSaver extends com.mapconductor.compose.map.BaseMapViewSaver<com.mapconductor.maptiler.MapTilerViewState> {
public static final java.lang.String KEY_DESIGN_ID;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/mapconductor/maptiler/MapTilerDesign.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.mapconductor.maptiler

import java.net.URL
import com.mapconductor.core.map.AttributionRule
import com.mapconductor.core.map.BlankMapStyle
import com.mapconductor.core.map.MapDesignTypeInterface
import com.maptiler.maptilersdk.map.style.MTMapReferenceStyle
import com.maptiler.maptilersdk.map.style.MTMapStyleVariant
import java.net.URL

/**
* MapTiler の地図デザイン(リファレンススタイル + バリアント)を表すインターフェース。
Expand Down
81 changes: 79 additions & 2 deletions src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ import com.mapconductor.core.map.LocalMapOverlayRegistry
import com.mapconductor.core.map.LocalMapServiceRegistry
import com.mapconductor.core.map.LocalMapViewController
import com.mapconductor.core.map.MapCameraPosition
import com.mapconductor.core.map.MapViewStyle
import com.mapconductor.core.map.MapViewStyleEffect
import com.mapconductor.core.map.StyleMutationStore
import com.mapconductor.core.map.VectorStyleAsDesign
import com.mapconductor.core.map.VectorStyleMutationSupportKey
import com.mapconductor.core.map.VectorStyleSupportKey
import com.mapconductor.core.map.applyStyleMutations
import com.mapconductor.core.marker.MarkerRenderingSupportKey
import com.mapconductor.core.marker.MarkerTilingOptions
import com.maptiler.maptilersdk.events.MTEvent
Expand Down Expand Up @@ -78,6 +83,15 @@ fun MapTilerMapView(
onCameraMoveStart: OnCameraMoveHandler? = null,
onCameraMove: OnCameraMoveHandler? = null,
onCameraMoveEnd: OnCameraMoveHandler? = null,
/**
* How the map looks, when the app states it rather than naming a design.
*
* A vector style *is* the basemap. `com.mapconductor:vectorstyle` builds
* one; what happens underneath depends on this backend and the app does
* not have to know.
*/
style: MapViewStyle? = null,
onStyleDiagnostics: ((List<String>) -> Unit)? = null,
content: (@Composable MapViewScope.() -> Unit)? = null,
) {
MapTilerMapSurface(
Expand All @@ -91,6 +105,8 @@ fun MapTilerMapView(
onCameraMoveStart = onCameraMoveStart,
onCameraMove = onCameraMove,
onCameraMoveEnd = onCameraMoveEnd,
style = style,
onStyleDiagnostics = onStyleDiagnostics,
content = content,
)
}
Expand Down Expand Up @@ -121,6 +137,15 @@ fun MapTilerMapSurface(
onCameraMove: OnCameraMoveHandler? = null,
onCameraMoveEnd: OnCameraMoveHandler? = null,
onControllerReady: ((MapTilerMapViewController) -> Unit)? = null,
/**
* How the map looks, when the app states it rather than naming a design.
*
* A vector style *is* the basemap. `com.mapconductor:vectorstyle` builds
* one; what happens underneath depends on this backend and the app does
* not have to know.
*/
style: MapViewStyle? = null,
onStyleDiagnostics: ((List<String>) -> Unit)? = null,
content: (@Composable MapViewScope.() -> Unit)? = null,
) {
val context = LocalContext.current
Expand All @@ -136,20 +161,59 @@ fun MapTilerMapSurface(
// `key(design.id)` の**外**に置く: 中に置くと、デザイン切替のたびに
// 「新しい合成の put → 古い合成の onDispose で remove」の順で走り、
// 登録が消える。スタイル切替はまさにこの capability が起こす。
// 同じ理由で、スタイルを「その場で」書き換える capability も `key(design.id)` の外。
// こちらが登録されていれば `VectorStyle` はデザイン差し替え(= WebView 作り直し)を
// せずルールだけ送る。コントローラは `key` の中で作り直されるので、スタイルは箱越しに
// 読む — 古い `MTStyle` を掴んだままだと、地図が捨てたスタイルに書き込むことになる。
val liveController = remember(state) { mutableStateOf<MTMapViewController?>(null) }
// コントローラも同じ理由で箱越し。スタイルの設置を `key` の中で呼ぶと、
// デザイン切替ごとに dispose → install が走り、設置がデザインを変えるので止まらない。
val liveMapController = remember(state) { mutableStateOf<MapTilerMapViewController?>(null) }
val mutations =
remember(state) {
StyleMutationStore { list ->
applyStyleMutations(
MapTilerStyleMutationTarget { liveController.value?.style },
list,
)
}
}

DisposableEffect(state) {
state.serviceRegistry.put(
VectorStyleSupportKey,
VectorStyleAsDesign(state) { url, rules ->
VectorStyleAsDesign(
state,
// CUSTOM(URL) 以外は MapTiler クラウドの名前付きスタイルで、
// キーが要るので取りに行けない。null を返して「調整するものが
// 無い」と言わせる。
urlOf = { design ->
(design.referenceStyle as? MTMapReferenceStyle.CUSTOM)?.url?.toString()
},
) { url, rules ->
MapTilerDesign(
id = "vector-style:$url",
referenceStyle = MTMapReferenceStyle.CUSTOM(URL(url)),
attributionRules = rules,
)
},
)
onDispose { state.serviceRegistry.remove(VectorStyleSupportKey) }
state.serviceRegistry.put(VectorStyleMutationSupportKey, mutations)
onDispose {
state.serviceRegistry.remove(VectorStyleSupportKey)
state.serviceRegistry.remove(VectorStyleMutationSupportKey)
}
}

// スタイルの設置も `key(design.id)` の外。何が起きるかはこのバックエンドが
// 宣言した能力で決まる(MapTiler は文書もその場書き換えも受けられる)。
MapViewStyleEffect(
state = state,
style = style,
controller = liveMapController.value,
onDiagnostics = onStyleDiagnostics,
)

// デザイン(スタイル)切替時はコントローラと WebView を作り直し、確実に新スタイルを反映する。
key(design.id) {
val mtController = remember { MTMapViewController(context) }
Expand All @@ -165,6 +229,7 @@ fun MapTilerMapSurface(
state.serviceRegistry.put(MarkerRenderingSupportKey, it.markerRenderingSupport)
// RN のホストはここでコントローラを受け取り、共通基底へ渡す。
// `remember` の中なのでスタイル切替でコントローラを作り直したときだけ鳴る。
liveMapController.value = it
onControllerReady?.invoke(it)
}
}
Expand Down Expand Up @@ -225,6 +290,18 @@ fun MapTilerMapSurface(
object : MTMapViewDelegate {
override fun onMapViewInitialized() {
mapReady = true
liveController.value = mtController
// 適用済みのスタイル調整はスタイルを読み込み直した時点で消える。
// ここが戻し場所。
//
// **このプロバイダにはスタイル読み込みの通知がこれしかない。**
// ブリッジが中継するイベントのうち `ready` は MapLibre の
// `load` の中で 1 度だけ鳴り、`styledata` はプロパティを 1 つ
// 変えるたびに鳴る(= 再適用が自分を呼び続ける)。Compose は
// デザイン切替でコントローラごと作り直すのでここで足りるが、
// 非 Compose ホストが `setMapDesignType` を直接呼んだ場合は
// 調整が落ちたままになる。
mutations.onStyleLoaded()
controller.reapplyRasterLayers()
controller.reapplyPolylines()
controller.reapplyPolygons()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ internal fun MapTilerMapViewController.recoverLogicalCameraPosition(raw: MapCame
)
val distanceBackward =
altitude * cos(pitchAbsRad) * tan(pitchAbsRad) * MapTilerMapViewController.NEGATIVE_TILT_TARGET_DISTANCE_SCALE
val originalPosition = Spherical.computeOffset(shiftedCenter, distanceBackward, CameraBearing.toNativeHeading(raw.bearing) + 180.0)
val originalPosition =
Spherical.computeOffset(
shiftedCenter, distanceBackward,
CameraBearing.toNativeHeading(raw.bearing) + 180.0,
)

return raw.copy(
position = originalPosition,
Expand Down Expand Up @@ -194,7 +198,9 @@ internal fun MapTilerMapViewController.toCameraOptions(camera: MapCameraPosition
cos(tiltAbsRad) *
tan(tiltAbsRad) *
MapTilerMapViewController.NEGATIVE_TILT_TARGET_DISTANCE_SCALE
val target = Spherical.computeOffset(camera.position, distanceForward, CameraBearing.toNativeHeading(camera.bearing))
val target =
Spherical
.computeOffset(camera.position, distanceForward, CameraBearing.toNativeHeading(camera.bearing))
val adjustedZoom =
camera.zoom + MapTilerMapViewController.NEGATIVE_TILT_ZOOM_OFFSET_AT_MAX_TILT * (tiltAbsDeg / 60.0)

Expand Down
Loading
Loading