diff --git a/demo-app/src/commonMain/kotlin/dev/sargunv/maplibrecompose/demoapp/util.kt b/demo-app/src/commonMain/kotlin/dev/sargunv/maplibrecompose/demoapp/util.kt index 4c37b73b..411b4045 100644 --- a/demo-app/src/commonMain/kotlin/dev/sargunv/maplibrecompose/demoapp/util.kt +++ b/demo-app/src/commonMain/kotlin/dev/sargunv/maplibrecompose/demoapp/util.kt @@ -88,7 +88,7 @@ val Platform.supportsLayers: Boolean get() = isAndroid || isIos val Platform.supportsBlending: Boolean - get() = isAndroid || isIos + get() = isAndroid || isIos || isWeb val Platform.usesMaplibreNative: Boolean get() = isAndroid || isIos diff --git a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/compose/AndroidMapView.kt b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/compose/AndroidMapView.kt index ebfe7383..e02d2a56 100644 --- a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/compose/AndroidMapView.kt +++ b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/compose/AndroidMapView.kt @@ -15,6 +15,7 @@ import dev.sargunv.maplibrecompose.core.AndroidMap import dev.sargunv.maplibrecompose.core.AndroidScaleBar import dev.sargunv.maplibrecompose.core.MaplibreMap import org.maplibre.android.MapLibre +import org.maplibre.android.gestures.AndroidGesturesManager import org.maplibre.android.maps.MapLibreMapOptions import org.maplibre.android.maps.MapView @@ -63,6 +64,12 @@ internal fun AndroidMapView( mapView -> currentMapView = mapView mapView.getMapAsync { map -> + map.setGesturesManager(AndroidGesturesManager(context), false, false) + mapView.isClickable = false + mapView.isLongClickable = false + mapView.isFocusable = false + mapView.setFocusableInTouchMode(false) + mapView.requestDisallowInterceptTouchEvent(false) currentMap = AndroidMap( mapView = mapView, diff --git a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/AndroidMap.kt b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/AndroidMap.kt index 835c331b..8594cb0a 100644 --- a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/AndroidMap.kt +++ b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/AndroidMap.kt @@ -212,15 +212,8 @@ internal class AndroidMap( override fun setMaximumFps(maximumFps: Int) = mapView.setMaximumFps(maximumFps) override fun setGestureSettings(value: GestureSettings) { - map.uiSettings.isRotateGesturesEnabled = value.isRotateGesturesEnabled - map.uiSettings.isScrollGesturesEnabled = value.isScrollGesturesEnabled - map.uiSettings.isTiltGesturesEnabled = value.isTiltGesturesEnabled - map.uiSettings.isZoomGesturesEnabled = value.isZoomGesturesEnabled - // on iOS, there is no setting for enabling quick zoom (=double-tap, hold and move up or down) - // and zoom in by a double tap separately, so isZoomGesturesEnabled turns on or off ALL zoom - // gestures - map.uiSettings.isQuickZoomGesturesEnabled = value.isZoomGesturesEnabled - map.uiSettings.isDoubleTapGesturesEnabled = value.isZoomGesturesEnabled + map.uiSettings.setAllGesturesEnabled(false) + map.gesturesManager.detectors.clear() } override fun setOrnamentSettings(value: OrnamentSettings) { diff --git a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/MaplibreMap.kt b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/MaplibreMap.kt index 298157dc..9a660cdd 100644 --- a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/MaplibreMap.kt +++ b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/MaplibreMap.kt @@ -1,5 +1,7 @@ package dev.sargunv.maplibrecompose.compose +import androidx.compose.foundation.gestures.rememberTransformableState +import androidx.compose.foundation.gestures.transformable import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -8,6 +10,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.DpOffset import co.touchlab.kermit.Logger import dev.sargunv.maplibrecompose.compose.engine.LayerNode @@ -20,6 +23,7 @@ import dev.sargunv.maplibrecompose.core.StandardMaplibreMap import dev.sargunv.maplibrecompose.core.Style import dev.sargunv.maplibrecompose.core.util.PlatformUtils import io.github.dellisd.spatialk.geojson.Position +import kotlin.math.log2 import kotlin.math.roundToInt import kotlinx.coroutines.launch @@ -178,8 +182,26 @@ public fun MaplibreMap( val scope = rememberCoroutineScope() + val density = LocalDensity.current + + val transformableState = rememberTransformableState { zoomChange, offsetChange, rotationChange -> + val center = cameraState.screenLocationFromPosition(cameraState.position.target) + val newCenter = + center - with(density) { DpOffset(offsetChange.x.toDp(), offsetChange.y.toDp()) } + val newTarget = cameraState.positionFromScreenLocation(newCenter) + val newZoom = + (cameraState.position.zoom + log2(zoomChange)).coerceIn( + zoomRange.start.toDouble(), + zoomRange.endInclusive.toDouble(), + ) + val newBearing = (cameraState.position.bearing - rotationChange).mod(360.0) + println("newTarget: $newTarget, newZoom: $newZoom, newBearing: $newBearing") + cameraState.position = + cameraState.position.copy(target = newTarget, zoom = newZoom, bearing = newBearing) + } + ComposableMapView( - modifier = modifier.fillMaxSize(), + modifier = modifier.fillMaxSize().transformable(transformableState), styleUri = styleUri, update = { map -> when (map) { diff --git a/lib/maplibre-compose/src/desktopMain/kotlin/dev/sargunv/maplibrecompose/core/WebviewMap.kt b/lib/maplibre-compose/src/desktopMain/kotlin/dev/sargunv/maplibrecompose/core/WebviewMap.kt index b522c935..8ad8f66b 100644 --- a/lib/maplibre-compose/src/desktopMain/kotlin/dev/sargunv/maplibrecompose/core/WebviewMap.kt +++ b/lib/maplibre-compose/src/desktopMain/kotlin/dev/sargunv/maplibrecompose/core/WebviewMap.kt @@ -106,11 +106,11 @@ internal class WebviewMap(private val bridge: WebviewBridge) : MaplibreMap { } override suspend fun asyncSetGestureSettings(value: GestureSettings) { - bridge.callVoid("setTiltGesturesEnabled", value.isTiltGesturesEnabled) - bridge.callVoid("setZoomGesturesEnabled", value.isZoomGesturesEnabled) - bridge.callVoid("setRotateGesturesEnabled", value.isRotateGesturesEnabled) - bridge.callVoid("setScrollGesturesEnabled", value.isScrollGesturesEnabled) - bridge.callVoid("setKeyboardGesturesEnabled", value.isKeyboardGesturesEnabled) + bridge.callVoid("setTiltGesturesEnabled", false) + bridge.callVoid("setZoomGesturesEnabled", false) + bridge.callVoid("setRotateGesturesEnabled", false) + bridge.callVoid("setScrollGesturesEnabled", false) + bridge.callVoid("setKeyboardGesturesEnabled", false) } override suspend fun animateCameraPosition(finalPosition: CameraPosition, duration: Duration) {} diff --git a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/compose/IosMapView.kt b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/compose/IosMapView.kt index 1ea2a556..704db352 100644 --- a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/compose/IosMapView.kt +++ b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/compose/IosMapView.kt @@ -65,7 +65,9 @@ internal fun IosMapView( UIKitView( modifier = modifier.fillMaxSize(), properties = - UIKitInteropProperties(interactionMode = UIKitInteropInteractionMode.NonCooperative), + UIKitInteropProperties( + interactionMode = UIKitInteropInteractionMode.Cooperative(delayMillis = Int.MAX_VALUE) + ), factory = { MLNMapView( frame = diff --git a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/IosMap.kt b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/IosMap.kt index 20d503e3..222b55ba 100644 --- a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/IosMap.kt +++ b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/IosMap.kt @@ -41,7 +41,10 @@ import cocoapods.MapLibre.MLNOrnamentPositionTopLeft import cocoapods.MapLibre.MLNOrnamentPositionTopRight import cocoapods.MapLibre.MLNStyle import cocoapods.MapLibre.MLNZoomLevelForAltitude +import cocoapods.MapLibre.allowsRotating +import cocoapods.MapLibre.allowsScrolling import cocoapods.MapLibre.allowsTilting +import cocoapods.MapLibre.allowsZooming import dev.sargunv.maplibrecompose.core.util.toBoundingBox import dev.sargunv.maplibrecompose.core.util.toCGPoint import dev.sargunv.maplibrecompose.core.util.toCGRect @@ -294,10 +297,13 @@ internal class IosMap( } override fun setGestureSettings(value: GestureSettings) { - mapView.rotateEnabled = value.isRotateGesturesEnabled - mapView.scrollEnabled = value.isScrollGesturesEnabled - mapView.allowsTilting = value.isTiltGesturesEnabled - mapView.zoomEnabled = value.isZoomGesturesEnabled + mapView.rotateEnabled = false + mapView.scrollEnabled = false + mapView.allowsTilting = false + mapView.zoomEnabled = false + mapView.allowsZooming = false + mapView.allowsScrolling = false + mapView.allowsRotating = false } private fun calculateMargins( diff --git a/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/compose/WebMapView.kt b/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/compose/WebMapView.kt index 38e6b62b..ba79fc00 100644 --- a/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/compose/WebMapView.kt +++ b/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/compose/WebMapView.kt @@ -51,7 +51,7 @@ internal fun WebMapView( HtmlElement( modifier = modifier.onGloballyPositioned { maybeMap?.resize() }, - // zIndex = "-1", // TODO figure out pointer interop + zIndex = "-1", factory = { document.createElement("div").unsafeCast().apply { style.apply { diff --git a/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/core/JsMap.kt b/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/core/JsMap.kt index 87c7fafb..fe3b8683 100644 --- a/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/core/JsMap.kt +++ b/lib/maplibre-compose/src/jsMain/kotlin/dev/sargunv/maplibrecompose/core/JsMap.kt @@ -132,43 +132,13 @@ internal class JsMap( } override fun setGestureSettings(value: GestureSettings) { - if (value.isTiltGesturesEnabled) { - impl.touchPitch.enable() - } else { - impl.touchPitch.disable() - } - - if (value.isRotateGesturesEnabled) { - impl.dragRotate.enable() - impl.keyboard.enableRotation() - impl.touchZoomRotate.enableRotation() - } else { - impl.dragRotate.disable() - impl.keyboard.disableRotation() - impl.touchZoomRotate.disableRotation() - } - - if (value.isScrollGesturesEnabled) { - impl.dragPan.enable() - } else { - impl.dragPan.disable() - } - - if (value.isZoomGesturesEnabled) { - impl.doubleClickZoom.enable() - impl.scrollZoom.enable() - impl.touchZoomRotate.enable() - } else { - impl.doubleClickZoom.disable() - impl.scrollZoom.disable() - impl.touchZoomRotate.disable() - } - - if (value.isKeyboardGesturesEnabled) { - impl.keyboard.enable() - } else { - impl.keyboard.disable() - } + impl.touchPitch.disable() + impl.dragRotate.disable() + impl.keyboard.disable() + impl.dragPan.disable() + impl.doubleClickZoom.disable() + impl.scrollZoom.disable() + impl.touchZoomRotate.disable() } private var compassPosition: String? = null