Quick start: maplibre_gl (Flutter, vector)
maplibre_gl uses MapLibre Native on Android and iOS and MapLibre GL JS on the web. The vector style is sharper than raster tiles, labels stay upright when the map rotates, tiles are lighter and the thermal, skyway, take-off and landing layers come with the style.
1. Dependency
flutter pub add updraft_maps maplibre_gl:0.28.0
updraft_maps is Updraft's client package: style address (updraftStyleString), key header (applyUpdraftKey), thermal filter (setUpdraftThermalFilter) and attribution line (UpdraftAttribution).
Platform setup (Android minSdk, iOS version and location permissions) is in the package's own documentation; the web needs no extra setup.
2. Map
// Updraft quick start 3: maplibre_gl (MapLibre Native on Android/iOS, MapLibre GL JS on web)
// with the Updraft "pilot eye" vector style and the thermal grid, through the updraft_maps package.
import 'package:flutter/material.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:updraft_maps/maplibre_gl.dart';
import 'raster_map.dart'
show openAttributionRules, updraftTiles, updraftTilesKey;
class VectorMapScreen extends StatefulWidget {
const VectorMapScreen({super.key, this.dark = false});
/// `pilot-dark` instead of `pilot-light`.
final bool dark;
@override
State<VectorMapScreen> createState() => _VectorMapScreenState();
}
class _VectorMapScreenState extends State<VectorMapScreen> {
MapLibreMapController? _controller;
UpdraftTheme get _theme =>
widget.dark ? UpdraftTheme.dark : UpdraftTheme.light;
Future<void> _onMapCreated(MapLibreMapController controller) async {
_controller = controller;
// The key goes only to the Updraft tile server, as a header (Android and iOS; on web the
// public tile path is used, a browser key would be visible to everyone).
await applyUpdraftKey(
controller,
apiKey: updraftTilesKey,
tilesUrl: updraftTiles,
);
}
// Thermal grid for July, 12:00–14:00 local time, wind from the west (all values: ThermalFilter()).
Future<void> _onStyleLoaded() => setUpdraftThermalFilter(
_controller!,
ThermalFilter(month: 7, hourBucket: 6, windSector: 6),
theme: _theme,
tilesUrl: updraftTiles,
);
@override
Widget build(BuildContext context) => Stack(
children: [
MapLibreMap(
styleString: updraftStyleString(theme: _theme, tilesUrl: updraftTiles),
initialCameraPosition: const CameraPosition(
target: LatLng(36.56, 29.17),
zoom: 11.5,
),
onMapCreated: _onMapCreated,
onStyleLoadedCallback: _onStyleLoaded,
minMaxZoomPreference: const MinMaxZoomPreference(4, 17),
compassEnabled: true,
// MapLibre's own attribution button folds the text into a menu: show the line instead.
attributionButtonPosition: AttributionButtonPosition.topRight,
),
const UpdraftAttribution(thermals: true, onTap: openAttributionRules),
],
);
}
updraftTiles, updraftTilesKey and openAttributionRules come from the file of the flutter_map example.
3. Key
- On Android and iOS
applyUpdraftKeyadds the key withsetCustomHeadersonly to requests for the Updraft tile server (the filter is a regular expression,updraftHeaderFilter).setHttpHeadersadds it to every request; use the filtered call so that no other server receives your key. - On the web headers cannot be set; the browser uses the public tile path without a key (limited per client address). To use MapLibre GL JS directly on the web: MapLibre quick start.
- A key inside an app must have the
tilesscope only.
4. Thermal grid
The style draws the thermal grid with the "all months, all day, all wind directions" breakdown (source thermals, layers thermals-fill and thermals-line). For another breakdown the TileJSON address of the source changes with the filter, e.g. https://maps.updraftmaps.com/thermals?month=7&hour_bucket=6. maplibre_gl cannot change a source address; setUpdraftThermalFilter adds the source again with that address and rebuilds the two layers with the style's properties, under the skyway layers (call it after the style has loaded, onStyleLoadedCallback in the example). Parameters: Tiles and styles.
5. Attribution
MapLibre's own attribution button folds the text into a menu; the rules require a visible line. The example moves the button to a corner and writes the line under the map with UpdraftAttribution(thermals: true) (with the DWD wind data attribution, as the thermal grid is shown) (Attribution).