MapLibre Compose
repository·main·Indexed 19 days ago
https://github.com/maplibre/maplibre-composeA Compose Multiplatform wrapper for MapLibre SDKs that enables interactive map rendering across Android, iOS, Desktop, and Web. The desktop implementation utilizes a Native FFI architecture requiring Java 25 and supports Vulkan (Linux, Windows) and Metal (macOS) backends. It includes a Desktop Host SPI for custom graphics integration, a dedicated threading model for graphics contexts, and support for offline map packs.
What's inside MapLibre Compose
- MapLibre Compose is a Compose Multiplatform wrapper around the MapLibre SDKs. It allows developers to integrate interactive maps into Compose-based user interfaces across multiple platforms, including Android, iOS, Desktop, and Web.
Overview of MapLibre Compose Multiplatform
mainMapLibre Compose is a Compose Multiplatform wrapper around the MapLibre SDKs. It allows developers to integrate interactive maps into Compose-based user interfaces across multiple platforms.
Supported Platforms:
- Android: Uses MapLibre Native.
- iOS: Uses MapLibre Native.
- Desktop (JVM): Uses MapLibre Native.
- Web (JS): Uses MapLibre GL JS.
- Web (Wasm): Currently not supported.
Use Material 3 extensions for MapLibre Compose
mainThemaplibre-compose-material3module provides Material 3-based UI controls for MapLibre maps. These serve as an alternative to the default map ornaments, allowing you to integrate map controls into a Material 3 design system within Compose Multiplatform applications.Explore the MapLibre Compose module structure
mainThemaplibre-composemodule is the primary entry point for using MapLibre within Compose Multiplatform. It is organized into several functional packages that cover the full lifecycle of map interaction, from core rendering to advanced expression styling.Current platform support and roadmap
mainMapLibre Compose currently provides support for Android and iOS.
Development is actively working towards parity for other platforms. Key upcoming features include:
- Desktop Parity: Support for macOS, Windows, and Linux (via Kotlin JVM bindings to MapLibre Native).
- JS Parity: Support for Compose apps in the browser using Kotlin JS (backed by MapLibre GL JS).
- WASM Parity: Support for Compose apps in the browser using Kotlin WASM.
Note that features like programmatic layer styling, offline management, and platform location services may vary in availability depending on the target platform and its current development status.
Use the core MapLibre Compose APIs
mainThe library is organized into the following functional areas:
- Core Map Components: Use
org.maplibre.compose.mapfor the primary map composable and its fundamental components. - Camera Control: Use
org.maplibre.compose.camerato manage camera positioning, movement, and utilities. - Offline Management: Use
org.maplibre.compose.offlineto handle offline map data and caching strategies. - Layers and Sources: Use
org.maplibre.compose.layersandorg.maplibre.compose.sourcesto declaratively add map layers and data sources to your map view. - Map Expressions: For styling and data-driven logic, use the expression system:
- DSL (Recommended): Use
org.maplibre.compose.expressions.dslas your primary API for creating MapLibre expressions using a Kotlin DSL. - AST: Use
org.maplibre.compose.expressions.astto interact with the underlying Abstract Syntax Tree. - Value System: Use
org.maplibre.compose.expressions.valueto access the type system, interfaces, and enums that define expression values.
- DSL (Recommended): Use
- Core Map Components: Use
Manage Map Styles, Sources, and Layers via FFI
mainThe Desktop implementation uses a generic JSON style API.
Source Objects
Sources act as live descriptors:
- Before attachment: They store the source ID, type, data, and options.
- After attachment: Mutable operations call the FFI immediately on the owner thread.
- Supported types: GeoJSON, vector, raster, raster DEM, image, and custom/computed sources.
Layer Objects
Layers store ID, type, source ID, source layer, zoom range, visibility, filter, layout properties, and paint properties.
- Before attachment: Setters update the descriptor. Adding a layer emits one complete layer JSON object.
- After attachment: Setters use
setLayerProperty,setLayerFilter, and layer move/remove APIs.
Images
To add images, convert Compose
ImageBitmappixels to tightly packed premultiplied RGBA8 and usesetStyleImage. Note thatImageResizeOptions(stretch metadata) are currently a known limitation in the FFI boundary.Desktop MapLibre Native FFI Architecture Overview
mainThe desktop implementation of MapLibre for Compose Multiplatform is transitioning from a JNI-based architecture to a Native FFI (Foreign Function Interface) architecture. This rewrite requires Java 25 as the minimum runtime for desktop compilation, execution, and packaging.
Key architectural components include:
- Host SPI (Service Provider Interface): A public interface that allows the default Skiko host to be replaced by alternative hosts (e.g., a
compose-glfwfixture). - DesktopMapSession: Manages the runtime pumping, event translation, camera operations, frame scheduling, and teardown.
- Native Render Paths: Supports Linux Vulkan, Windows Vulkan, and macOS Metal via FFI.
- Resource Boundary: Uses a specific runtime resource boundary for loading Compose resources.
- Host SPI (Service Provider Interface): A public interface that allows the default Skiko host to be replaced by alternative hosts (e.g., a
How location tracking and visualization work in MapLibre Compose
mainLocation support is composed of three main functional parts that work together to track and visualize user position:
- Providers: Collect raw data.
rememberDefaultLocationProviderprovides GPS/position data, andrememberDefaultOrientationProviderprovides sensor-based orientation data. LocationPuck: A visual component that draws the user's current position and bearing on the map.LocationTrackingEffect: A Composable effect used to subscribe to updates and optionally keep the camera in sync with the user's movement or orientation.
Note on Platforms: Android and iOS include default providers. On Desktop and Web, you must supply a custom
LocationProviderorOrientationProvideras the defaults will throw an error.- Providers: Collect raw data.
Check platform support and progress
mainSupport levels vary by platform. Android and iOS currently have the most complete support (approximately 90%), while Web (20%) and Desktop (15%) are still in development. Before starting a project, verify the current status of specific features on your target platform in the official status table.Manage camera bearing with LocationTrackingEffect
mainThe
LocationTrackingEffectcontrols how the camera rotates in response to location and orientation updates. You can choose from several bearing update modes:Bearing update mode Camera behavior IGNOREKeep the current camera bearing. ALWAYS_NORTHReset the camera to north. TRACK_COURSERotate the camera with the user's direction of movement. TRACK_ORIENTATIONRotate the camera with the device orientation. TRACK_AUTOMATICUse the more accurate course or orientation measurement. Note that
LocationPuck(bearing = ...)only rotates the visual indicator on the map, whereasLocationTrackingEffectcontrols the actual camera rotation.Understand the Desktop Host Integration SPI
mainMapLibre Compose provides a Desktop Host SPI in
org.maplibre.compose.desktopthat allows applications to replace the default Skiko-based graphics integration with a custom host. This is useful for providing custom GPU contexts or render-target access (e.g., usingcompose-glfw).Key SPI Concepts
DesktopMapHostFactory: Reports supported backend combinations and creates a host surface.DesktopMapHost: Owns host graphics objects and provides a composable drawing surface.DesktopMapFrame: Describes a renderable target (extent, scale factor, timestamp, etc.).DesktopRenderTarget: Provides backend-neutral wrappers around native handles.DesktopMapRenderer: Handles surface availability, extent changes, and frames.LocalDesktopMapHostFactory: ACompositionLocalused to provide the host factory. The default implementation is the Skiko host.
By providing a custom implementation of these interfaces, you can decouple MapLibre's map behavior from the specific Compose host used.