Added function to draw custom markers with Kotlin DSL Canvas API #1
@ -3,9 +3,12 @@ package centre.sciprog.maps.compose
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import centre.sciprog.maps.GmcBox
|
||||||
|
|
||||||
typealias FeatureId = String
|
typealias FeatureId = String
|
||||||
|
|
||||||
@ -41,6 +44,21 @@ fun FeatureBuilder.circle(
|
|||||||
id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun FeatureBuilder.custom(
|
||||||
|
position: Pair<Double, Double>,
|
||||||
|
id: FeatureId? = null,
|
||||||
|
customFeatureBuilder: DrawScope.(Offset) -> Unit,
|
||||||
|
) = addFeature(id, object : MapCustomFeature(position = position.toCoordinates()) {
|
||||||
|
override fun drawFeature(drawScope: DrawScope, offset: Offset) {
|
||||||
|
customFeatureBuilder(drawScope, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBoundingBox(zoom: Int): GmcBox {
|
||||||
|
return GmcBox(position.toCoordinates(), position.toCoordinates())
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
fun FeatureBuilder.line(
|
fun FeatureBuilder.line(
|
||||||
aCoordinates: Pair<Double, Double>,
|
aCoordinates: Pair<Double, Double>,
|
||||||
bCoordinates: Pair<Double, Double>,
|
bCoordinates: Pair<Double, Double>,
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package centre.sciprog.maps.compose
|
package centre.sciprog.maps.compose
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
@ -31,6 +33,13 @@ class MapFeatureSelector(val selector: (zoom: Int) -> MapFeature) : MapFeature(d
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class MapCustomFeature(
|
||||||
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
|
val position: GeodeticMapCoordinates
|
||||||
|
) : MapFeature(zoomRange) {
|
||||||
|
abstract fun drawFeature(drawScope: DrawScope, offset: Offset)
|
||||||
|
}
|
||||||
|
|
||||||
class MapCircleFeature(
|
class MapCircleFeature(
|
||||||
val center: GeodeticMapCoordinates,
|
val center: GeodeticMapCoordinates,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
|
@ -21,6 +21,7 @@ expect fun MapView(
|
|||||||
computeViewPoint: (canvasSize: DpSize) -> MapViewPoint,
|
computeViewPoint: (canvasSize: DpSize) -> MapViewPoint,
|
||||||
features: Map<FeatureId, MapFeature>,
|
features: Map<FeatureId, MapFeature>,
|
||||||
onClick: MapViewPoint.() -> Unit = {},
|
onClick: MapViewPoint.() -> Unit = {},
|
||||||
|
onFeatureClick: (FeatureId) -> Unit = {},
|
||||||
//TODO consider replacing by modifier
|
//TODO consider replacing by modifier
|
||||||
config: MapViewConfig = MapViewConfig(),
|
config: MapViewConfig = MapViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
@ -32,13 +33,14 @@ fun MapView(
|
|||||||
initialViewPoint: MapViewPoint,
|
initialViewPoint: MapViewPoint,
|
||||||
features: Map<FeatureId, MapFeature> = emptyMap(),
|
features: Map<FeatureId, MapFeature> = emptyMap(),
|
||||||
onClick: MapViewPoint.() -> Unit = {},
|
onClick: MapViewPoint.() -> Unit = {},
|
||||||
|
onFeatureClick: (FeatureId) -> Unit = {},
|
||||||
config: MapViewConfig = MapViewConfig(),
|
config: MapViewConfig = MapViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {},
|
buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {},
|
||||||
) {
|
) {
|
||||||
val featuresBuilder = MapFeatureBuilder(features)
|
val featuresBuilder = MapFeatureBuilder(features)
|
||||||
featuresBuilder.buildFeatures()
|
featuresBuilder.buildFeatures()
|
||||||
MapView(mapTileProvider, { initialViewPoint }, featuresBuilder.build(), onClick, config, modifier)
|
MapView(mapTileProvider, { initialViewPoint }, featuresBuilder.build(), onClick, onFeatureClick, config, modifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -47,6 +49,7 @@ fun MapView(
|
|||||||
box: GmcBox,
|
box: GmcBox,
|
||||||
features: Map<FeatureId, MapFeature> = emptyMap(),
|
features: Map<FeatureId, MapFeature> = emptyMap(),
|
||||||
onClick: MapViewPoint.() -> Unit = {},
|
onClick: MapViewPoint.() -> Unit = {},
|
||||||
|
onFeatureClick: (FeatureId) -> Unit = {},
|
||||||
config: MapViewConfig = MapViewConfig(),
|
config: MapViewConfig = MapViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {},
|
buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {},
|
||||||
@ -62,5 +65,5 @@ fun MapView(
|
|||||||
)
|
)
|
||||||
MapViewPoint(box.center, zoom)
|
MapViewPoint(box.center, zoom)
|
||||||
}
|
}
|
||||||
MapView(mapTileProvider, computeViewPoint, featuresBuilder.build(), onClick, config, modifier)
|
MapView(mapTileProvider, computeViewPoint, featuresBuilder.build(), onClick, onFeatureClick, config, modifier)
|
||||||
}
|
}
|
@ -6,14 +6,15 @@ import androidx.compose.material.Text
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Home
|
import androidx.compose.material.icons.filled.Home
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.window.Window
|
import androidx.compose.ui.window.Window
|
||||||
import androidx.compose.ui.window.application
|
import androidx.compose.ui.window.application
|
||||||
import centre.sciprog.maps.GeodeticMapCoordinates
|
import centre.sciprog.maps.GeodeticMapCoordinates
|
||||||
import centre.sciprog.maps.MapViewPoint
|
import centre.sciprog.maps.MapViewPoint
|
||||||
import centre.sciprog.maps.compose.*
|
import centre.sciprog.maps.compose.*
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.*
|
||||||
import io.ktor.client.engine.cio.CIO
|
import io.ktor.client.engine.cio.*
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -44,15 +45,25 @@ fun App() {
|
|||||||
mapTileProvider,
|
mapTileProvider,
|
||||||
viewPoint,
|
viewPoint,
|
||||||
onClick = { coordinates = focus },
|
onClick = { coordinates = focus },
|
||||||
|
onFeatureClick = {
|
||||||
|
|
||||||
|
},
|
||||||
config = MapViewConfig(inferViewBoxFromFeatures = true)
|
config = MapViewConfig(inferViewBoxFromFeatures = true)
|
||||||
) {
|
) {
|
||||||
val pointOne = 55.568548 to 37.568604
|
val pointOne = 55.568548 to 37.568604
|
||||||
val pointTwo = 55.929444 to 37.518434
|
val pointTwo = 55.929444 to 37.518434
|
||||||
|
val pointThree = 60.929444 to 37.518434
|
||||||
|
|
||||||
image(pointOne, Icons.Filled.Home)
|
image(pointOne, Icons.Filled.Home)
|
||||||
|
|
||||||
//remember feature Id
|
//remember feature Id
|
||||||
val circleId: FeatureId = circle(pointTwo)
|
val circleId: FeatureId = custom(position = pointThree) {
|
||||||
|
drawRect(
|
||||||
|
color = Color.Red,
|
||||||
|
topLeft = it,
|
||||||
|
size = Size(20f, 20f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
line(pointOne, pointTwo)
|
line(pointOne, pointTwo)
|
||||||
text(pointOne, "Home")
|
text(pointOne, "Home")
|
||||||
|
@ -41,6 +41,7 @@ actual fun MapView(
|
|||||||
computeViewPoint: (canvasSize: DpSize) -> MapViewPoint,
|
computeViewPoint: (canvasSize: DpSize) -> MapViewPoint,
|
||||||
features: Map<FeatureId, MapFeature>,
|
features: Map<FeatureId, MapFeature>,
|
||||||
onClick: MapViewPoint.() -> Unit,
|
onClick: MapViewPoint.() -> Unit,
|
||||||
|
onFeatureClick: (FeatureId) -> Unit,
|
||||||
config: MapViewConfig,
|
config: MapViewConfig,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
) {
|
) {
|
||||||
@ -219,7 +220,10 @@ actual fun MapView(
|
|||||||
feature.color.toPaint()
|
feature.color.toPaint()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is MapCustomFeature -> drawIntoCanvas { canvas ->
|
||||||
|
val offset = feature.position.toOffset()
|
||||||
|
feature.drawFeature(this, offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user