Skip to content
This site is a preview of the main branch. The published documentation is at maplibre.org.

Capture a map image

A MapSnapshotter renders a map to an ImageBitmap without showing it on screen. Use it to let users share or save a view of the map, or to show a static map image where an interactive map is not needed.

Create a snapshotter with MapRuntime.createSnapshotter. Use the same runtime as your map, so the snapshotter uses the same request settings. rememberMapState uses DefaultMapRuntime.instance unless you pass another runtime. This button captures what a displayed map shows:

App.kt
val snapshotter =
remember(mapState.style.baseStyle) {
DefaultMapRuntime.instance.createSnapshotter(
baseStyle = mapState.style.baseStyle,
content = mapContent,
)
}
DisposableEffect(snapshotter) { onDispose { snapshotter.close() } }
val scope = rememberCoroutineScope()
val screenDensity = LocalDensity.current
val screenLayoutDirection = LocalLayoutDirection.current
Button(
onClick = {
scope.launch {
try {
val image =
snapshotter.capture(DpSize(640.dp, 360.dp)) {
cameraPosition = mapState.cameraPosition
density = screenDensity
layoutDirection = screenLayoutDirection
}
onCapture(image)
} catch (error: MapSnapshotException) {
onError(error)
}
}
}
) {
Text("Share map")
}

To match the displayed map, the example passes the map’s base style and mapContent, the same function that declares the map’s sources and layers in rememberMapState. It also copies the map’s camera position, the screen density, and the layout direction into the request. In a snapshotter, LocalMapState is null, so content that reads it must handle that. How the map composes shows content that works in both places.

The request size is in dp. The image size in pixels is that size multiplied by the request density. With a density of 2, the 640 × 360 dp request above produces a 1280 × 720 pixel image.

The image contains only the map. It does not include Compose UI, such as map controls, or attribution text. Most map data requires attribution, so show it with the image. After a capture, snapshotter.style.attributions() returns the attribution of each source as HTML.

capture throws MapSnapshotException when rendering fails, for example when a tile cannot load.

Keep one snapshotter for repeated captures, and call capture with a new request each time. Close it when you no longer need it, as the DisposableEffect in the example does.