Adding data to the map¶
Sources and layers¶
As covered in Styling the map, the data displayed on the map is defined by the style, which is provided as a URI to a JSON object. However, this library provides a way to add additional data to the map at runtime.
A map style primarily consists of sources and layers. Sources contain the data
included on the map, and layers configure how that data is displayed. With
MapLibre Compose, you can dynamically configure sources and layers with
@Composable
functions:
MaplibreMap(styleUri = "https://tiles.openfreemap.org/styles/liberty") {
val tiles = getBaseSource(id = "openmaptiles")
CircleLayer(id = "example", source = tiles, sourceLayer = "poi")
}
The above example shows how to add a layer referring to a source from the base style, but you can also declare new sources:
val amtrakRoutes =
rememberGeoJsonSource(
id = "amtrak-routes",
uri = Res.getUri("files/data/amtrak_routes.geojson"),
)
LineLayer(
id = "amtrak-routes-casing",
source = amtrakRoutes,
color = const(Color.White),
width = const(6.dp),
)
LineLayer(
id = "amtrak-routes",
source = amtrakRoutes,
color = const(Color.Blue),
width = const(4.dp),
)
The full breadth of layer styling options available is out of scope for this guide; see the MapLibre Style Specification for more information.
Expressions¶
MapLibre styles support expressions, which define a formula for computing the
value of a property at runtime. The expressions specification is
based on JSON, but this library provides a Kotlin DSL for expressing these
formulas with some type safety. Where suitable, Compose types like Dp
,
Color
, and DpOffset
are used instead of their corresponding raw JSON-like
types. When passing a constant value instead of a formula, wrap it in const()
to turn it into an expression.
LineLayer(
id = "amtrak-routes",
source = amtrakRoutes,
cap = const(LineCap.Round),
join = const(LineJoin.Round),
color = const(Color.Blue),
width =
interpolate(
type = exponential(const(1.2f)),
input = zoom(),
5 to const(0.4.dp),
6 to const(0.7.dp),
7 to const(1.75.dp),
20 to const(22.dp),
),
)
Anchoring layers¶
The default behavior for layers defined by Composable functions is to place them
at the top of the map, above the base style layers. However, you can insert them
at other positions in the stack of layers with Anchor
:
Anchor.Above("road_motorway") { LineLayer(id = "amtrak-routes", source = amtrakRoutes) }
Anchors to insert layers at the Bottom
, Top
, Above
a base layer, Below
a
base layer, or Replace
a base layer are provided.
Interacting with layers¶
Layer composables provide click listeners, similar to the map itself. You can listen for clicks on a layer and consume or pass those click events:
CircleLayer(
id = "amtrak-stations",
source = amtrakStations,
onClick = { features ->
println("Clicked on ${features[0].json()}")
ClickResult.Consume
},
)
Click listeners are called on the map first, then in layer order from the top to the bottom of the map. The first listener to consume the event will prevent it from propagating to subsequent listeners.