maplibre_flutter_gpu 0.0.1
maplibre_flutter_gpu: ^0.0.1 copied to clipboard
MapLibre maps for Flutter, rendered with Flutter GPU.
maplibre_flutter_gpu #
Render MapLibre maps with Flutter GPU without Platform Views. Smooth, Synchronized, Widget-friendly, with support for custom 3D rendering.
Widgets on the map #
Have you ever wanted to place a Flutter widget on a map as a marker?
With conventional map plugins, that widget drifts while the map moves.
Flutter and the map use different rendering engines, so their frames cannot stay perfectly synchronized. The effect becomes more noticeable on lower-end devices and can make the map difficult to use.
MapLibre Flutter GPU solves this by letting Flutter render the map and the widgets together.
Everything (Text and Symbols) is a Widget #
Every label and symbol on the map is a Flutter widget. You can also place any widget you like at any geographic coordinate.
Use Flutter to restyle place names and regional labels, make them tappable, or bring them to life with animations. Map content and your interface share the same widget system and stay synchronized while the camera moves.
Place 3D objects in the map space #
Because the map is rendered with Flutter GPU, you can modify its 3D space directly from Dart.
New to Flutter GPU? That is fine. Modern LLMs can already help implement a surprisingly wide range of Flutter GPU effects.
Turn a flat map pin into a 3D object positioned in geographic space. Animate cars along roads. If you want to go further, you could even build a flight simulator or an FPS game around a real map.
Supporting platforms #
MapLibre Flutter GPU currently supports the following platforms.
- iOS
- Android
- macOS
Windows and Linux support is planned after Flutter 3.47 reaches the stable channel. Both platforms have already been tested with Flutter 3.44, but release builds are blocked until Flutter 3.47 becomes stable.
Web is not supported because Flutter GPU is unavailable there.
Getting started #
Add MapLibre Flutter GPU to your project with this command.
flutter pub add maplibre_flutter_gpu
Import the package and add a MapLibreMap widget.
import 'package:flutter/material.dart';
import 'package:maplibre_flutter_gpu/maplibre_flutter_gpu.dart';
class MapPage extends StatefulWidget {
const MapPage({super.key});
@override
State<MapPage> createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
MapLibreMapController? _controller;
@override
Widget build(BuildContext context) => Scaffold(
body: MapLibreMap(
styleString: MapLibreStyles.openfreemapLiberty,
initialCameraPosition: const CameraPosition(
target: LatLng(35.6812, 139.7671),
zoom: 13,
),
onMapCreated: (controller) {
_controller = controller;
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_controller?.animateCamera(
CameraUpdate.newLatLngZoom(
const LatLng(35.6586, 139.7454),
15,
),
);
},
child: const Icon(Icons.location_searching),
),
);
}
MapLibreMap constructor #
Map and lifecycle #
| Parameter | Type | Default | Description |
|---|---|---|---|
initialCameraPosition |
CameraPosition? |
Style camera | Camera used when the map is created. Use the controller for later changes. |
styleString |
String |
MapLibreStyles.demo |
Style URL, raw style JSON, absolute file path, file URI, or Flutter asset path. |
onMapCreated |
MapCreatedCallback? |
null |
Receives the controller after renderer creation. The initial style may still be loading. |
onStyleLoadedCallback |
OnStyleLoadedCallback? |
null |
Runs after the active style loads and after every successful style replacement. |
onCameraMove |
OnCameraMoveCallback? |
null |
Reports camera changes caused by gestures or controller commands. |
onCameraIdle |
OnCameraIdleCallback? |
null |
Runs after camera movement settles. It does not mean all map work has finished. |
onMapIdle |
OnMapIdleCallback? |
null |
Runs whenever style, camera, and pending map work have fully settled. |
onMapClick |
OnMapClickCallback? |
null |
Reports a tap using logical screen coordinates and geographic coordinates. |
onMapLongClick |
OnMapClickCallback? |
null |
Reports the start of a long press using screen and geographic coordinates. |
Camera and gestures #
| Parameter | Type | Default | Description |
|---|---|---|---|
cameraTargetBounds |
CameraTargetBounds |
Unbounded | Limits the geographic camera target. |
minMaxZoomPreference |
MinMaxZoomPreference |
Unbounded | Limits camera zoom. |
minMaxTiltPreference |
MinMaxTiltPreference |
Unbounded | Limits camera tilt in degrees. |
rotateGesturesEnabled |
bool |
true |
Enables two-finger rotation. |
scrollGesturesEnabled |
bool |
true |
Enables one-finger panning. |
zoomGesturesEnabled |
bool |
true |
Enables pinch and scroll-wheel zoom. |
tiltGesturesEnabled |
bool |
true |
Enables three-finger vertical tilt. |
doubleClickZoomEnabled |
bool? |
Follows zoom gestures | Enables double-tap zoom independently. |
gestureOptions |
MapGestureOptions |
const MapGestureOptions() |
Configures gesture animation, thresholds, and sensitivity. |
trackCameraPosition |
bool |
false |
Makes the controller notify its listeners when the camera changes. |
Map controls #
| Parameter | Type | Default | Description |
|---|---|---|---|
compassEnabled |
bool |
true |
Displays the compass when its builder is available. |
compassViewPosition |
CompassViewPosition? |
Top right | Positions the compass. |
compassViewMargins |
Point<num>? |
(8, 8) |
Sets compass insets in logical pixels. |
compassBuilder |
CompassWidgetBuilder? |
Default compass | Builds the compass from its bearing and reset callback. |
logoEnabled |
bool |
false |
Displays the MapLibre logo when its builder is available. |
logoViewPosition |
LogoViewPosition? |
Bottom left | Positions the logo. |
logoViewMargins |
Point<num>? |
(8, 8) |
Sets logo insets in logical pixels. |
logoBuilder |
WidgetBuilder? |
Default logo | Builds the MapLibre logo. |
attributionButtonEnabled |
bool |
true |
Displays the attribution button. |
attributionButtonPosition |
AttributionButtonPosition? |
Bottom right | Positions the attribution button. |
attributionButtonMargins |
Point<num>? |
(8, 8) |
Sets attribution-button insets in logical pixels. |
onAttributionLinkTap |
AttributionLinkCallback? |
null |
Handles links selected in the default attribution dialog. |
attributionButtonBuilder |
AttributionButtonWidgetBuilder? |
Default button | Builds the attribution button. |
attributionDialogBuilder |
WidgetBuilder? |
Default dialog | Builds the dialog opened by the attribution button. |
scaleControlEnabled |
bool |
false |
Displays a scale bar when its value can be calculated. |
scaleControlPosition |
ScaleControlPosition |
Bottom left | Positions the scale bar. |
scaleControlUnit |
ScaleControlUnit |
Metric | Selects metric or imperial distance. |
scaleControlMargins |
Point<num> |
(8, 8) |
Sets scale-bar insets in logical pixels. |
scaleControlMaxWidth |
double |
80 |
Sets the maximum scale-bar width in logical pixels. |
scaleControlAvoidLogo |
bool |
true |
Moves the scale bar above a logo in the same bottom corner. |
scaleControlLogoOffset |
double |
27 |
Sets the logo avoidance offset in logical pixels. |
scaleControlBuilder |
ScaleControlWidgetBuilder? |
Default scale bar | Builds the scale bar from a ScaleBarValue. |
Flutter widgets and custom GPU content #
| Parameter | Type | Default | Description |
|---|---|---|---|
foregroundLoadColor |
Color? |
Transparent | Value supplied to the loading builder. |
loadingBuilder |
MapLoadingWidgetBuilder? |
Default overlay | Builds the widget displayed while a style loads. |
errorBuilder |
MapErrorWidgetBuilder? |
ErrorWidget |
Builds the replacement widget when map creation fails. |
symbolIconBuilder |
SymbolWidgetBuilder? |
Style sprite | Builds every placed symbol icon as a Flutter widget. Return null to hide one. |
symbolTextBuilder |
SymbolWidgetBuilder? |
Style text | Builds every placed symbol label as a Flutter widget. Return null to hide one. |
symbolFadeDuration |
Duration |
150 ms | Controls symbol fade-in and fade-out. |
symbolCullingPadding |
EdgeInsets |
120 horizontal, 60 vertical | Keeps symbols built slightly outside the viewport. |
gpuMapRenderCallback |
MapLibreGpuRenderCallback? |
null |
Records geographic GPU geometry inside the map's 3D sequence with shared depth. |
gpuRenderCallback |
MapLibreGpuRenderCallback? |
null |
Records a final Flutter GPU overlay above the map. |
gpuRepaint |
Listenable? |
null |
Requests new frames for animated custom GPU content. |
gpuOverlayDepthMode |
MapLibreGpuDepthMode |
isolated |
Selects isolated or shared depth for the final GPU overlay. |
MapLibreMap creates and owns its MapLibreMapController. Receive the
controller through onMapCreated, then use it to move the camera, change the
style, manage layers, inspect source metadata, and convert between geographic
and screen coordinates. Do not dispose the controller yourself.
MapLibre performs symbol placement and collision detection, while Flutter builds the result. Customize map labels and icons with ordinary widgets.
MapLibreMap(
symbolTextBuilder: (context, symbol) => DecoratedBox(
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.85),
borderRadius: BorderRadius.circular(6),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
child: Text(symbol.data.text),
),
),
symbolIconBuilder: (context, symbol) => const Icon(
Icons.location_on,
color: Colors.red,
),
)
Custom symbol widgets are visual children and intentionally ignore pointer
events so gestures can reach the map. Use onMapClick or place your own widget
with a Stack when it needs direct interaction.
For operations that depend on the loaded style, wait for
onStyleLoadedCallback.
MapLibreMap(
onMapCreated: (controller) {
_controller = controller;
},
onStyleLoadedCallback: () async {
await _controller?.setLayerVisibility('building-3d', true);
},
)
MapLibreMapController #
The controller is used to change a map after it has been created. Save the
instance received by onMapCreated for later use.
Style and layers #
| Method | Description |
|---|---|
setStyle(styleString) |
Starts loading a style URL, JSON document, file, or Flutter asset. |
getStyle() |
Returns the active style JSON when available. |
getLayerIds() |
Returns the IDs of the loaded style layers. |
getSourceIds() |
Returns the IDs of the loaded style sources. |
getSourceAttributions() |
Returns unique source attribution strings. |
setLayerVisibility(layerId, visible) |
Shows or hides a loaded layer. |
getLayerVisibility(layerId) |
Returns layer visibility, or null when the layer does not exist. |
addFillExtrusionLayer(...) |
Adds a maplibre_gl-compatible fill-extrusion layer. |
addLayer(...) |
Adds a fill-extrusion layer from a LayerProperties object. |
setLayerProperties(layerId, properties) |
Updates the properties of a loaded layer. |
removeLayer(layerId) |
Removes a loaded layer. |
setFilter(layerId, filter) |
Applies a JSON-compatible filter and throws when the layer is missing. |
setLayerFilter(layerId, filter) |
Applies a JSON filter string and reports whether the layer was found. |
getFilter(layerId) |
Returns the parsed filter for a layer. |
Camera and coordinates #
| Method or property | Description |
|---|---|
cameraPosition |
Latest camera position cached by the controller. |
isCameraMoving |
Whether a programmatic camera transition is active. |
moveCamera(update) |
Applies a camera update immediately. |
animateCamera(update, duration: ...) |
Animates to a camera update. |
easeCamera(update, duration: ..., interpolation: ...) |
Applies a camera update with configurable easing. |
queryCameraPosition() |
Refreshes and returns the current camera position. |
toScreenLocation(latLng) |
Converts a geographic coordinate to logical screen pixels. |
toScreenLocationBatch(latLngs) |
Converts multiple geographic coordinates in one call. |
toScreenOffset(latLng) |
Synchronous Offset version of toScreenLocation. |
toLatLng(screenLocation) |
Converts logical screen pixels to a geographic coordinate. |
toLatLngOffset(screenLocation) |
Synchronous Offset version of toLatLng. |
getVisibleRegion() |
Returns the current visible geographic bounds. |
getMetersPerPixelAtLatitude(latitude) |
Returns map resolution at a latitude. |
setCameraBounds(...) |
Updates target, zoom, and tilt constraints. |
updateContentInsets(...) |
Updates camera padding in logical pixels. |
resetNorth() |
Resets the camera bearing to north. |
getPlacedLabels() |
Returns the latest native label-placement snapshot. |
isMapIdle |
Whether camera, style, and pending map work are settled. |
The controller belongs to its MapLibreMap. Do not call dispose() yourself
and do not use it after the map widget has been removed.
See the example app and the standalone examples
for Flutter markers, runtime style controls, and custom Flutter GPU rendering.
This package is currently in beta. API and runtime stability are not guaranteed. Android in particular still needs testing across a wider range of devices and environments.
Bug reports, device compatibility results, and other feedback are welcome in GitHub Issues.