arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 41

v6

Loading...

Loading...

Loading...

Loading...

Getting Started

Loading...

Loading...

Loading...

Loading...

Loading...

Usage

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Layers

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Tile Servers

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Plugins

Loading...

Loading...

Loading...

Loading...

Showcase

A collection of cool projects that use flutter_map

hashtag
Apply To Be Listed

Want to advertise your project here? For more information, and to apply, please see:

  • The application form for non-OSS projectsarrow-up-right

  • (it's free!)

circle-check

We also appreciate donations, and we're extremely grateful for anything you can spare.

We'll donate 15% of what we receive to the OpenStreetMap Foundation, as a thanks for their excellent work.

For more information, details about benefits, and the link to donate, please see .

hashtag
Non-OSS Sponsors

hashtag
OSS and/or Non-Profit Projects

circle-info

There's many more that aren't listed here! See the , and the #showcase channel for more minor projects on our Discord server.

hashtag
Plugins

Your advert here!

Support us and get a top advert slot! More information in .

Your advert here!

More information in .

The application form for OSS and/or non-profit projectsarrow-up-right
dependents list on GitHubarrow-up-right
Plugins Listchevron-right
Cover

Map Marker

Your places organizer

https://www.mapmarker.app/
Cover

Every Door

Open Source100% Non-Profit

The most efficient OpenStreetMap editor for surveying shops and benches

https://every-door.app/
Cover

Ente Photos

Open Source

End-to-end encrypted alternative to Google Photos

https://ente.io/

flutter_map

A versatile mapping package for Flutter. Simple and easy to learn, yet completely customizable and configurable, it's the best choice for mapping in your Flutter app.

hashtag
Feature Highlights

chevron-rightHow does flutter_map compare to other mapping libraries?hashtag

This usually refers to libraries such as 'mapbox_gl' and 'google_maps_flutter'. In most ways, it is better, in some it is worse.

flutter_map wins on:

  • Less vendor lock-in (and potentially reduced costs) You're not locked into a particular tile server with us - choose from hundreds of options, or build your own!

  • Customizability & extensibility Add all sorts of layers to display custom widgets and data on top of your map, and choose from flutter_map's many community maintained plugins to add even more functionality!

  • Ease of use/setup We don't require any API keys or platform specific setup (other than enabling the Internet permission!), so you can get started quicker, and make changes without fear of breaking your release application.

  • Support quality and frequency Most questions are answered and resolved within 12-24 hours, thanks to our dedicated maintainers and community.

However, alternatives may win on:

  • Performance* flutter_map's performance is very adequate for the vast majority of applications, and many big businesses use FM to provide maps in their Flutter app. However, if you're using high-thousands of Markers or Polygons and such like, alternatives may win, purely because they use platform views and GL, and so can do calculations outside of Dart.

  • ... and that's pretty much it 😉

hashtag
Demonstration

Setting up an interactive and compliant map is simpler than making your lunch-time coffee! It can be accomplished in just under 30 lines and a minute or two to install.

This code snippet demonstrates everything you need for a simple map (in just over 20 lines!), but of course, FM is capable of much more than just this, and you could find yourself lost in the many options available and possibilities opened!

hashtag
Get Help

Not quite sure about something? No problem. Please get in touch via any of these methods, and we'll be with you as soon as possible. Please remember that we are volunteers, so we cannot guarantee (fast) support.

  • For bug reports & feature requests: check the FAQs then GitHub Issuesarrow-up-right

  • For support & everything else: check the FAQs then flutter_map Discord serverarrow-up-right

circle-info

Due to time shortages, wait times for feature request implementations are currently extremely long and may not happen at all.

We'd love to have your contributions to add your own or others' pull requests!

hashtag
FAQs

We get quite a lot of similar questions, so please check if your question is here before you ask!

chevron-rightHow can I use a custom map style? How can I prevent POI/labels rotating when the map rotates? How can I remove certain POI/labels from the map?hashtag

Unfortunately, this library cannot provide this functionality. It has no control over the tiles displayed in the TileLayer. This is a limitation of the technology, not this library.

This is because raster tiles are just images generated by a 3rd party tile server (dictated by your URL template), and therefore cannot be changed by the library that displays the tiles. Filters can be applied to the entire tile, such as an emulated dark mode, but these effects do not look great.

However, tilesets can be styled. This is the most effective way of using custom styles. These methods may help you with this:

  • You may wish to use a commercial service like Mapbox Studio, which allows you to style multiple tilesets. See .

  • Alternatively, you can experiment with vector tiles. These are not pre-rendered, and so allow any style you desire to be applied on the fly. See .

  • Your last option is to serve tiles yourself. See .

chevron-rightHow can I route a user between two locations? Why does the Polyline only go in a straight line between two points?hashtag

See .

chevron-rightHow can I add a Marker where the user's location is? How can I center the map on the user's location?hashtag

This is beyond the scope of flutter_map. However, you can use the community maintained plugin 'flutter_map_location_marker'arrow-up-right to do this.

Alternatively, use the 'location' and 'compass' packages to generate a stream of the user's location and heading, and feed that to a Marker using a StreamBuilder.

chevron-rightWhy does the map disappear/go grey when I zoom in far? Why does the map stop zooming in even though I know there are more zoom levels?hashtag

If tiles are disappearing when you zoom in, the default grey background of the FlutterMap widget will shine through. This usually means that the tile server doesn't support these higher zoom levels.

If you know that there are more tiles available further zoomed in, but flutter_map isn't showing them and scaling a particular zoom level instead, it's likely because the TileLayer.maxNativeZoom property is set too low (it defaults to 19).

To set/change the zoom level at which FM starts scaling tiles, change the TileLayer.maxNativeZoom property. To set/change the max zoom level that can actually be zoomed to (hard limit), use MapOptions.maxZoom.

chevron-rightHow can I make the map 3D, or view it as a globe?hashtag

Unfortunately, this isn't supported, partially due to lack of time on the maintainer's part to implement this feature, partially due to technical limitations. PRs are welcome!

🗺️ Supports any* map style

We natively support any static raster tile server, including from a web server or even from the local file system or app asset store. No more vendor lock-in!

💪 Stress-free setup and use

Migrating from a commercial library such as Google Maps has never been easier! No more complex platform-specific setup, no more API keys: just add a widget and you're done.

🧩 Wide ecosystem of plugins

In the unlikely event that flutter_map doesn't natively contain something you need, just check to see if there's a community maintained plugin that does what you need!

➕ Add other map features easily

Add polygons, polylines, and markers/pins to your map easily and quickly. Markers support displaying any widget you might want.

arrow-up-right
arrow-up-right
arrow-up-right
arrow-up-right
arrow-up-right
How Does It Work?chevron-right
Apply To Be Listed
Apply To Be Listed

Examples

flutter_map provides an example application showcasing much of its functionality. In some cases, the example app contains undocumented functionality, so it's definitely worth checking out!

hashtag
Live Web Demo

circle-info

import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';

@override
Widget build(BuildContext context) {
  return FlutterMap(
    options: MapOptions(
      initialCenter: LatLng(51.509364, -0.128928),
      initialZoom: 9.2,
    ),
    children: [
      TileLayer(
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        userAgentPackageName: 'com.example.app',
      ),
      RichAttributionWidget(
        attributions: [
          TextSourceAttribution(
            'OpenStreetMap contributors',
            onTap: () => launchUrl(Uri.parse('https://openstreetmap.org/copyright')),
          ),
        ],
      ),
    ],
  );
}
Note that the web demo is built automatically from the 'master' brancharrow-up-right, so may not reflect the the latest release on pub.dev.
circle-exclamation

Please don't abuse the web demo! It runs on limited bandwidth and won't hold up to thousands of loads.

If you're going to be straining the application, please see Prebuilt Artifacts, and serve the application yourself.

hashtag
Prebuilt Artifacts

If you can't build from source for your platform, our GitHub Actions CI system compiles the example app to GitHub Artifacts for Windows, Web, and Android.

The Windows and Android artifacts just require unzipping and installing the .exe or .apk found inside.

The Web artifact requires unzipping and serving, as it contains more than one unbundled file. You may be able to use dhttpdarrow-up-right for this purpose.

circle-info

Note that these artifacts are built automatically from the 'master' brancharrow-up-right, so may not reflect the the latest release on pub.dev.

hashtag
Build From Source

If you need to use the example app on another platform, you can build from source, using the 'example' directory of the repository.

Using Mapbox
Other Options
Vector Tiles

Credits & Contributing

hashtag
Credits

Huge thanks to everyone who uses, supports, and/or contributes to flutter_map in any way, you've helped make the most popular non-commercially aimed mapping solution for Flutter!

In particular, thanks go to:

  • All the current maintainers:

    • @ibrierley

    • @JaffaKetchup

    • @mootw (previously @MooNag)

  • All the previous maintainers:

    • John P Ryan - the original founder of this project, over at AppTree Software

    • @kengu

  • The authors of this documentation:

    • @JaffaKetchup

  • Anyone who has contributed to making flutter_map:

  • Anyone who has made plugins for flutter_map:

  • Anyone who has donated to flutter_map:

hashtag
Contributing

We're always happy to receive improvements and fixes, so please submit them whenever you can! A few key points are listed below.

circle-info

Many feature additions are more suitable for plugins, instead of being added to the core. This is aimed to reduce the future maintenance burden/cost on the maintainers.

If we deny your PR for this reason, please do consider publishing a plugin, and we'll be happy to add it to the ! See for more information.

  • If your PR will add a major or breaking change, please discuss it with us first, via the Issue Tracker We don't want to waste your time if we think it's more appropriate for a plugin, and it helps to make a clear plan before starting work

  • Create a draft PR as soon as work starts, and take it out of draft status when ready for review Keep everyone in the loop, so no-one tries working on the same thing as you

  • Don't change the package version, GitHub workflows, lints, or any other meta files without clarification

hashtag
Apply To Be A Maintainer

Raster vs Vector Tiles

circle-info

It is important to note that 'flutter_map' only supports raster tiles natively. Vector tiles can be used with a community maintained plugin.

This is described in more detail at the bottom of this page.

There are 2 main types of tiles a server can serve: raster and vector; each has their own advantages and drawbacks. This page is designed to help you choose a type for your app, and help you use vector tiles if you choose to.

hashtag
Raster Tiles

Raster tiles are the 'older' type of tile, and are raster images (usually .png or .jpg). These tiles are good because they can render quickly and easily, can be viewed without special software, and are readily available from most mapping services. As such, this makes them the popular choice for beginners.

However, raster tiles cannot be easily themed: a theme needs a whole new set of map tiles. This makes apps using light and dark themes have mismatching maps. As well as this, raster tiles usually have larger file sizes meaning slower download times, and they can become blurred/pixelated when viewed at a larger scale: a problem for users when zooming between zoom levels. Another issue is that shapes/text inside tiles cannot be rotated, hence the name 'static tiles': therefore, rotating the map will not rotate the name of a road, for example.

hashtag
Vector Tiles

Vector tiles can be considered the 'newer' standard. These images might contain a specialised format (such as .pbf) dictating the mathematics and coordinates used to draw lines and shapes. Because these tiles are drawn at render time instead of at request/server time, theming can be used to make the map fit in better with an app's theme. The math-based image means that the images/tiles can be scaled without any loss of clarity.

However it does add complexity to the rendering process as each element needs to be parsed and painted individually, meaning an impact to performance. Text elements and certain shapes can also be rotated (unlike raster tiles) to match the user's orientation, not the orientation of the map; but calculating this rotation needs to be done every frame, meaning an even larger impact on performance.

hashtag
Using Vector Tiles

Due to the complications mentioned above, 'flutter_map' does not natively support vector tiles. However, vector tiles can be used with a to do this.

Using Thunderforest

circle-info

'flutter_map' is in no way associated or related with Thunderforest (or Gravitystorm Limited).

Thunderstorm's home page: thunderforest.comarrow-up-right Thunderstorm's pricing page: thunderforest.com/pricingarrow-up-right Thunderstorm's documentation page: thunderforest.com/docs/map-tiles-apiarrow-up-right

Thunderforest is a popular tiered-payment (with free tier) tile provider solution, especially for generic mapping applications. Note that using 'flutter_map' uses up your 'Map Tiles API' requests.

Installation

hashtag
Install

circle-check

All users should also to work with coordinates in 'flutter_map'.

Get Camera

The MapCamera object describes the map's current viewport. It does not provide methods to change it: that is the responsibility of a .

circle-info

The MapCamera object also provides access to some other helpful methods that depend on it, such as pointToLatLng & latLngToPoint.

Using Stadia Maps

circle-info

'flutter_map' is in no way associated or related with Stadia Maps.

Stadia Maps' home page: Stadia Maps' pricing page: Stadia Maps' documentation page:

To display their map tiles, Stadia Maps usually provides a 'Static Maps Base URL' for map styles. However, to integrate with 3rd-party APIs, they also provide a 'Raster XYZ PNGs URL' , and tiles requested through this endpoint consume 'Styled Raster Map Tiles' credits. This URL needs no extra configuration to integrate with flutter_map.

Programmatic Control

There's two ways to interact with the map - that is to control it, as well as receive data from it - and it's current viewport, aka. 'camera'.

hashtag
via User Gestures

The first way is through user interaction, where they perform gestures (such as drags/pans), and the map reacts automatically to those gestures to change the camera view of the map.

These are usually restricted by . It is possible to disable all input, either by disabling all gestures, or by wrapping the map with something like

Layers

To display anything on the map, you'll need to include at least one layer. This is usually a , which displays the map tiles themselves: without it, the map isn't really a very good map!

To insert a layer, add it to the children property. Other layers (sometimes referred to as 'feature layers', as they are map features) can then be stacked on top, where the last widget in the children list is topmost. For example, you might display a , or any widget as your own custom layer ()!

circle-info

Listen To Events

circle-info

To cause a widget inside FlutterMap's context to rebuild when the , , or changes, see .

This page's methods should only be used to listen to events from outside the FlutterMap's context.

Base Widget

Start by adding some to children, then configure the map in . Additionally, if required, add a MapController: .

hashtag
Placement Recommendations

It is recommended to make the map as large as possible, to allow it to display a lot of useful information easily.

Other Options

hashtag
Other Servers

There are plenty of other tile servers you can choose from, free or paid. Most provide a static tile service/API, usually called Static Tiles or just Tile Requests (if no vector tiles are supported).

If you're responsible for a tile server, and want to have your tile server and setup instructions listed in this documentation, please get in touch!

A good catalogue of servers (usually called Providers elsewhere) can be found at the websites below:

WMS Usage

flutter_map supports WMS tile servers through WMSTileLayerOptions - wmsOptions in TileLayers.

For usage, please refer to the Full API Reference, and the examples in the example app.

circle-check

Omit urlTemplate

Circle Layer

You can add circle areas to maps by making them out of a center coordinate and radius using CircleLayer and CircleMarkers.

circle-exclamation

Excessive use of circles may create performance issues.

Polygon Layer

You can add areas/shapes to maps by making them out of individual coordinates using PolygonLayer and Polygons.

circle-exclamation

Excessive use of polygons may create performance issues.

community maintained plugin (vector_map_tiles)arrow-up-right
Retina tiles (high-DPI) tiles are available. Use the URLs containing '@2x' instead of '{r}'. The maximum zoom level that Stadia Maps supports is 20, so it is recommended to set maxNativeZoom or maxZoom as such.
circle-exclamation

Attribution is required, see docs.stadiamaps.com/#legal-details-required-attributionarrow-up-right.

Consider using the RichAttributionWidget or SimpleAttributionWidgets, which meet the requirements.

hashtag
Styles

Stadia Maps offers a variety of ready-made map styles that don't require customization. URLs are found with the style: see the available map stylesarrow-up-right. The URL should be used as above.

hashtag
Vector Usage

Stadia Maps' also provides vector tiles. For more information about using vector tiles, please see Using Vector Tiles.

However, please note that this method of integration is still experimental. Many of the Stadia Maps styles utilize advanced features of the Mapbox GL JSON style language which are not yet well-supported.

stadiamaps.comarrow-up-right
stadiamaps.com/pricingarrow-up-right
docs.stadiamaps.comarrow-up-right
It is possible to add more than one TileLayer! Transparency in one layer will reveal the layers underneath.
circle-info

To display a widget in a sized and positioned box, similar to Overlay Image Layer, try the community maintained flutter_map_polywidget pluginarrow-up-right!

Each layer is isolated from the other layers, and so handles its own independent logic and handling. However, they can access and modify the internal state of the map, as well as respond to changes.

hashtag
Per-Layer Gesture Handling

By default, each layer acts translucently to gestures, meaning they can handle gestures themselves, but they also allow gestures to bubble down to other layers beneath them.

This behaviour can be disabled in the MapOptions, by setting .applyPointerTranslucencyToLayers false. Optionally, then, the TranslucentPointer widget can be wrapped around individal layers to achieve the desired effect.

hashtag
Mobile vs Static Layers

Most layers are 'mobile', such as the TileLayer. These use a MobileLayerTransformer widget internally, which enables the layer to properly move and rotate with the map's current camera.

However, some layers are 'static', such as the AttributionLayers. These aren't designed to move nor rotate with the map, and usually make use of a widget like Align and/or SizedBox.expand to achieve this.

Both of these layer types are defined in the same children list. Most of the time, static layers go atop mobile layers, so should be at the end of the list.

TileLayer
MarkerLayer
Creating New Layers
Example FlutterMap widget, containing multiple feature layers, atop a TileLayer
Example FlutterMap widget, containing multiple feature layers, atop a TileLayer
Support Us
IgnorePointer
.

hashtag
via Programmatic Means

When using programmatic means, there's two methods to most things, dependent on whether the context is within a FlutterMap (ie. usually a layer) or not.

If within FlutterMap's context, the methods usually cause automatic rebuilding. As well as the pages below, also see Creating New Layers.

Options
Control Camerachevron-right
Get Camerachevron-right
Listen To Eventschevron-right
As such, we recommend using a depth-based layout (eg. using Stacks) instead of a flat-based layout (eg. using Columns). The following 3rd party packages might help with creating a modern design:
  • https://pub.dev/packages/backdroparrow-up-right

  • https://pub.dev/packages/sliding_up_panelarrow-up-right

  • https://pub.dev/packages/material_floating_search_bar_2arrow-up-right

If you must restrict the widget's size, you won't find a height or width property. Instead, use a SizedBox or Column/Row & Expanded.

circle-info

The map widget will expand as much as possible.

To avoid errors about infinite/unspecified dimensions, ensure the map is contained within a constrained widget.

hashtag
Keep Alive

If the map is displayed lazily in something like a PageView, changing the page and unloading the map will cause it to reset to its initial positioning.

To prevent this, set MapOptions.keepAlive true, which will activate an internal AutomaticKeepAliveClientMixin. This will retain the internal state container in memory, even when it would otherwise be disposed.

Layers
Options
Control Camera
In the event that the LatLng object provided by that library conflicts with another, for example the one provided by Google Maps, you may need to use the 'as' suffixarrow-up-right.

hashtag
From pub.devarrow-up-right

Just import the package as you would normally, from the command line:

hashtag
From github.comarrow-up-right

circle-exclamation

Commits available from Git (GitHub) may not be stable. Only use this method if you have no other choice.

If you urgently need the latest version, a specific branch, or a specific fork, you can use this method.

First, use From pub.dev, then add the following lines to your pubspec.yaml file, as a root object:

hashtag
Additional Setup

hashtag
Web

Always force usage of the CanvasKit renderer instead of the HTML renderer, even on mobile devices.

The HTML renderer causes performance issues, and may also cause other bugs. Although the CanvasKit renderer does require slightly more Javascript (and therefore a longer download time), it works much better with flutter_map.

For more information about web renderers, see https://docs.flutter.dev/platform-integration/web/renderersarrow-up-right.

hashtag
Android

flutter_map needs to access the Internet to load tiles, in most cases. On Android, apps must include the INTERNET permission in their manifest. Add the following line to all manifests:

hashtag
MacOS

flutter_map needs to access the Internet to load tiles, in most cases. On MacOS, apps must include a dedicated entitlement. Add the following lines to 'macos/Runner/DebugProfile.entitlements' and 'macos/Runner/Release.entitlements':

hashtag
Import

After installing the package, import it into the necessary files in your project:

circle-exclamation

You must comply with the appropriate restrictions and terms of service set by your tile server. Failure to do so may lead to any punishment, at the tile server's discretion.

This library and/or the creator(s) are not responsible for any violations you make using this package.

The OpenStreetMap Tile Server (as used in this documentation) ToS can be found herearrow-up-right. Other servers may have different terms.

install 'latlong2'arrow-up-right
FlutterMap(
    mapController: MapController(),
    options: MapOptions(),
    children: [],
);
flutter pub add flutter_map latlong2
flutter pub add flutter_map_cancellable_tile_provider # OPTIONAL
pubspec.yaml
dependency_overrides:
    flutter_map:
        git:
            url: https://github.com/fleaflet/flutter_map.git
            # ref: main (custom branch/commit)
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
*.entitlements
<key>com.apple.security.network.client</key>
<true/>
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
@TesteurManiak
  • @josxha

  • @maRci002
    We rely on a standardized process and procedure to ensure top-quality releases
  • Use a clear (preferably Conventionalarrow-up-right) PR title This makes it easier for us to group commits for release and write correct CHANGELOGs

  • Contributor Listarrow-up-right
    Plugins List
    Plugins List
    Creating A Plugin
    Past Supporters
    hashtag
    Usage Inside Of A FlutterMap Child

    To get the camera from within the context of a FlutterMap widget, use MapCamera.of(context).

    circle-info

    Calling this method in a build method will cause the widget to automatically rebuild when the MapCamera changes. See Creating New Layers for more information.

    If this behaviour is unwanted, use Single Time instead.

    If this throws a StateError, try wrapping the concerned widget in a Builder, to ensure the FlutterMap widget is parenting the BuildContext. If this has no effect, use Usage Outside Of FlutterMap instead.

    hashtag
    Usage Outside Of FlutterMap

    hashtag
    Single Time

    To get the camera from outside the context of the FlutterMap widget, you'll need to setup a MapController first: see Control Camera > Usage Outside Of FlutterMap.

    Then, use the .camera getter.

    circle-exclamation

    Avoid using MapController.of(context).camera from within the context of FlutterMap, as it is redundant and less performant than using MapCamera.of(context) directly.

    hashtag
    Listen To Changes

    MapController
    Listen To Eventschevron-right
    When changes happen to
    FlutterMap
    's internal state (such as a change to the current
    ) it emits a MapEvent, which can be handled by you.

    hashtag
    Catching All Events

    There's two methods to catch all emitted MapEvents. These methods expose the raw MapEvent, and is recommended in cases where multiple events need to be caught, or there's no more specific callback method available in MapOptions (see Catching Specific Events).

    • Listening to a MapController's mapEventStream, which exposes events via a Stream

    • Specifying a callback method in MapOptions.onMapEvent

    hashtag
    Catching Specific Events

    If only a couple of events need to be caught, such as just an onTap handler, it is possible to avoid handling the raw Stream of MapEvents. Instead, MapOptions has callbacks available for the following events:

    • onTap

    • onLongPress

    • onPositionChanged

    • onPointerDown/onPointerUp/onPointerHover/onPointerCancel

    • onMapReady Primarily used for advanced MapController

    circle-info

    The MapEventTap event may be emitted (or the onTap callback called) 250ms after the actual tap occurred, as this is the acceptable delay between the two taps in a double tap zoom gesture.

    If this causes noticeable jank or a bad experience (for example, on desktop platforms), disable InteractiveFlag.doubleTapZoom:

    This disables the double tap handler, so the MapEventTap is emitted 'instantly' on tap.

    MapCamera
    MapOptions
    MapController
    Creating New Layers
    MapCamera
    circle-info

    Google Maps does not document a static raster tile server. Therefore, flutter_map is unable to show Google Maps.

    There is an undocumented endpoint available, however it violates the Google Maps Platform ToS.

    hashtag
    Serving Your Own Tiles

    Switch2OSM also provides detailed instructions on how to serve your own tiles: this can be surprisingly economical and enjoyable if you don't mind a few hours in a Linux console.

    However, this will require a very high-spec computer, especially for larger areas, and hosting this might be more complicated than it's worth. It's very difficult to fully understand the technologies involved.

    if using WMS tiles. The template is now specified in the
    baseUrl
    property of
    WMSTileLayerOptions
    .
    Consider enabling polygonCulling. This will prevent the calculation and rendering of polygons outside of the current viewport, however this may not work as expected in all situations.

    hashtag
    Polygon Manipulation

    'flutter_map' doesn't provide any public methods to manipulate polygons, as these would be deemed out of scope.

    However, some useful methods can be found in libraries such as 'latlong2' and 'poly_bool_dart'arrow-up-right. These can be applied to the input of Polygon's points argument, and the map will do it's best to try to render them. However, more complex polygons - such as those with holes - may be painted inaccurately, and may therefore require manual adjustment (of holePointsList, for example).

    hashtag
    onTap Support

    circle-exclamation

    There is no support for handling taps on polygons, due to multiple technical challenges. To stay up to date with this existing feature request, see the linked issue.

    An example Polygon
    CircleLayer(
      circles: [
        CircleMarker(
          point: LatLng(51.50739215592943, -0.127709825533512),
          radius: 10000,
          useRadiusInMeter: true,
        ),
      ],
    ),
    An example CircleMarker

    Supporters

    hashtag
    Support Us

    Please consider donating anything you can to us, we're extremely grateful for any and all donations. They keep us going and will allow us to cover any unforeseen or future costs, and potentially open up more doors and opportunities in future!

    We'll donate 15% of what we receive to the OpenStreetMap Foundation, as a thanks for their excellent work. The remainder goes directly to improving flutter_map.

    Enter a nickname to be listed below in Past Supporters, and enter your Discord username to be granted the "Supporter" role on our server and gain access to a special supporter-only chat channel. These benefits last indefinitely (but may take 48 hours to grant, as this is done manually).

    • & British specific payment methods

    • & European specific payment methods

    We support a variety of payment methods through Stripe, although some have lower fees for us. In general, cards have the highest fees, and the closer the method to the bank, the lower the fees. Donating in the GBP currency also reduces our fees, but we provide EUR checkout to add extra payment methods for those living in Europe. If paying in a currency other than your own, your bank's exchange rate/terms will apply. At this time, only one-time donations are accepted: please get in touch if you'd like to donate on a regular basis.

    circle-info

    We use Stripe for payments, analytics, and other business services. Stripe may collect personal data including via cookies and similar technologies. The personal data Stripe collects may include transactional data and identifying information about devices that connect to its services. Stripe uses this information to operate and improve the services it provides to us, including for fraud detection, loss prevention, authentication, and analytics related to the performance of its services. You can learn more about Stripe and read its privacy policy at .

    hashtag
    Past Supporters

    Huge thanks to all our past supporters, you help keep this project going. In no particular order, thanks to:

    • androidseb

    • Roundtrip

    • corepuncher

    Attribution Layer

    Before publishing your app to users, you should credit any sources you use, according to their Terms of Service.

    There are two built in methods to provide attribution, RichAttributionWidget and SimpleAttributionWidget, but you can also build your own using a simple Align widget.

    circle-exclamation

    You must comply with the appropriate restrictions and terms of service set by your tile server. Failure to do so may lead to any punishment, at the tile server's discretion.

    This library and/or the creator(s) are not responsible for any violations you make using this package.

    The OpenStreetMap Tile Server (as used above) ToS can be . Other servers may have different terms.

    circle-check

    Please consider crediting flutter_map. It helps us to gain more awareness, which helps make this project better for everyone!

    hashtag
    RichAttributionWidget

    An animated, interactive attribution layer that supports both logos/images (displayed permanently) and text (displayed in a popup controlled by an icon button adjacent to the logos).

    It is heavily customizable (in both animation and contents), and designed to easily meet the needs of most ToSs out of the box.

    For more information about configuration and all the many options this supports, see the in-code API documentation.

    hashtag
    SimpleAttributionWidget

    We also provide a more 'classic' styled box, similar to those found on many web maps. These are less customizable, but might be preferred over RichAttributionWidget for maps with limited interactivity.

    Creating A Plugin

    If one of the independently maintained plugins doesn't suit your needs, then you can create your own, to achieve maximum customizability.

    Most plugins create either new Tile Providers, or new Layers. Some plugins just provide additional useful tools.

    Creating New Tile Providerschevron-rightCreating New Layerschevron-right

    hashtag
    Submitting A New Plugin

    If you've made your own plugin that you're willing to share, please let us know in the #plugins channel on the flutter_map Discord server. We can then add it to the . We're always looking forward to see what you've made!

    When submitting a plugin, please ensure the plugin:

    • preferably includes 'flutter_map_' in the name, by convention

    • is preferably available via a standard pub.dev package installation

    • includes good documentation (at least to setup basic functionality), and a code example

    Using Mapbox

    circle-info

    'flutter_map' is in no way associated or related with Mapbox.

    Mapbox's Maps home page: mapbox.com/mapsarrow-up-right Mapbox's Maps pricing page: mapbox.com/pricing#mapsarrow-up-right Mapbox's Maps documentation: docs.mapbox.com/api/maps/static-tilesarrow-up-right

    To display their map tiles, Mapbox usually provides a 'Style URL' for map styles. However, to integrate with 3rd-party APIs, they also provide a 'CARTO Integration URL', and tiles requested through this endpoint consume the 'Static Tiles API' quota. This URL needs no extra configuration to integrate with flutter_map.

    The maximum zoom level that Mapbox supports is 22, so it is recommended to set maxNativeZoom or maxZoom as such.

    circle-exclamation

    Attribution is required, see .

    Consider using the , which meets the requirements by supporting both logo and text attribution.

    hashtag
    Integration

    hashtag
    Custom Styles

    Mapbox supports creating and using custom styled maps through Studio.

    1. Create a custom style using the editor

    2. Click "Share...", or the share icon

    3. Choose between Draft or Production

    hashtag
    Configuring

    The URL includes an '@2x' string, which forces usage of high-definition tiles on all displays, without extra setup.

    Should you need to let flutter_map interfere, and only use retina tiles on retina/high-density displays, replace it with the '{r}' placeholder, then see for more information.

    hashtag
    Prebuilt Styles

    Mapbox offers a variety of ready-made map styles that don't require customization. An example URL can be found in .

    This URL should be used as above, although you may need to insert the placeholders manually.

    Interaction Options

    The InteractionOptions object passed to MapOptions.interactiveOptions configures the gestures that the user can use to interact with the map. For example, disable rotation or configure cursor/keyboard rotation.

    hashtag
    Flags

    flags is a bitfieldarrow-up-right that enables and disables the vast majority of gestures. Although technically the type is of int, it is usually set with a combination of InteractiveFlags.

    circle-exclamation

    Note that some gestures must be configured by other means, either instead of using flags, or in addition to.

    By default, all gestures are enabled, but a non-interactive map can be created using none (and other options in addition).

    circle-info

    The recommended way to create an entirely non-interactive map is to wrap the FlutterMap widget in an IgnorePointer widget.

    Otherwise, to set flags, there's two methods:

    • Add flags, with the bitwise 'OR' (|) operator in-between For example, InteractiveFlag.drag | InteractiveFlag.rotate

    • Remove flags from all, using the & and ~ operators in-between For example, InteractiveFlag.all & ~InteractiveFlag.rotate

    hashtag
    Cursor/Keyboard Rotation

    Cursor/keyboard rotation is designed for desktop platforms, and allows the cursor to be used to set the rotation of the map whilst a (customizable) keyboard key (by default, any of the 'Control' keys) is held down.

    The CursorKeyboardRotationOptions object passed to the property with the corresponding name configures this behaviour. The CursorKeyboardRotationOptions.disabled() constructor can be used to disable cursor/keyboard rotation.

    There's many customization options, see the API docs for more information:

    hashtag
    "Win" Gestures

    circle-exclamation

    This is advanced behaviour that affects how gestures 'win' in the gesture arena, and does not usually need changing.

    Creating New Layers

    Creating a new map layer is a great way to achieve a more custom, performant, map design. For example, it might be used to display a scale bar, or overlay a grid.

    circle-info

    Check the Plugins List for layers that already implement the behaviour you wish to replicate.

    hashtag
    1. Creating A Layer Widget

    It starts with a normal StatelessWidget or StatefulWidget, which then starts its widget tree with a widget dependent on whether the layer is designed to be either 'mobile' or 'static', depending on the purpose of the layer. For more information, see .

    hashtag
    2. Hooking Into Inherited State

    Then, there are three possible methods that could be used to retrieve separate 'aspects' of the state of the map.

    Calling these inside a build method will also cause the layer to rebuild automatically when the depended-on aspects change.

    circle-exclamation

    Using these methods will restrict this widget to only being usable inside the context of a FlutterMap.

    Marker Layer

    You can add single point features - such as pins, labels, or markers - to maps using MarkerLayer and Markers.

    circle-check

    No more image only markers! Unlike other arrow-up-right😉, we allow usage of any widget as the marker.

    circle-exclamation

    Excessive use of markers may create performance issues.

    Consider using a clustering plugin to merge nearby markers together, reducing the work that needs to be done when rendering: .

    hashtag
    Alignment

    The marker widget will be centered over the geographic coordinate by default. However, this can be changed with the alignment argument, which aligns the widget relative to the point.

    The center of rotation when rotate is true will be the point.

    The default alignment for all Markers within a MarkerLayer can be set by changing the same property on the MarkerLayer.

    hashtag
    Rotation

    It is possible to enable the Marker to automatically counter-rotate to the camera's rotation, to ensure it remains facing upwards, via the rotate argument.

    The default alignment for all Markers within a MarkerLayer can be set by changing the same property on the MarkerLayer.

    circle-info

    There is no built-in support to rotate markers to a specific degree. However, this is easy to implement through a rotating widget, such as Transform.rotate.

    hashtag
    Handling Gestures

    There is no built-in support to handle gestures on Markers, such as taps. However, this is easy to implement using a standard GestureDetector.

    Overlay Image Layer

    You can overlay images on the map (for example, town or floor plans) using OverlayImageLayer and OverlayImages or RotatedOverlayImages.

    Example RotatedOverlayImage
    OverlayImageLayer(
      overlayImages: [
        OverlayImage(
          bounds: LatLngBounds(
            LatLng(45.3367881884556, 14.159452282322459),
            LatLng(45.264129635422826, 14.252585831779033),
          ),
          imageProvider: NetworkImage(),
        ),
      ],
    ),
    circle-exclamation

    There have been issues in the past where these images failed to appear properly, sometimes not showing up at all, sometimes showing up malformed or corrupted.

    If this issue occurs to you, and you're using Impeller, try disabling Impeller at launch/build time to see if the issue rectifies itself. If it does, this is an Impeller issue, and should be reported to the Flutter team.

    How Does It Work?

    circle-info

    If you don't know about standard map things, such as the latitude/longitude system and projections, you should probably read about these first!

    If you want a truly British insight into this, look no further than: & .

    Control Camera

    To control the map (such as moving it to a new position and zoom level), you'll need a MapController. The controller does not provide access to the current viewport/camera: that is the responsibility of .

    hashtag
    Usage Inside Of A FlutterMap Child

    To control the map from within the context of a FlutterMap

    Offline Mapping

    Using maps without an Internet connection is common requirement. Luckily, there are a few options available to you to implement offline mapping in your app.

    • Automatically store tiles as the user loads them through interacting with the map

    • Download an entire area/region of tiles in one shot, ready for a known no-Internet situation

    options: MapOptions(
        interactiveFlags: ~InteractiveFlag.doubleTapZoom,
    ),
    PolygonLayer(
      polygons: [
        Polygon(
          points: [LatLng(30, 40), LatLng(20, 50), LatLng(25, 45)],
          color: Colors.blue,
          isFilled: true,
        ),
      ],
    ),
    Maxi
  • ... and everyone else who donated anonymously

  • Donate with GBParrow-up-right
    Donate with EURarrow-up-right
    https://stripe.com/privacyarrow-up-right
    Plugins List
    Usage Inside initState()
    Mobile vs Static Layers
    class CustomMobileLayer extends StatelessWidget {
      const CustomMobileLayer({super.key});
    
      @override
      Widget build(BuildContext context) {    
        return MobileLayerTransformer(
          child: // your child here
        );
      }
    }
    class CustomStaticLayer extends StatelessWidget {
      const CustomStaticLayer({super.key});
    
      @override
      Widget build(BuildContext context) {
        return SizedBox.expand();
        // and/or
        return Align();
      }
    }
    final camera = MapCamera.of(context);
    final controller = MapController.of(context);
    final options = MapOptions.of(context);
    Scroll to the bottom of the dialog, and choose Third Party
  • Select "CARTO" from the dropdown menu

  • Click the copy button to copy the template URL

  • docs.mapbox.com/help/getting-started/attributionarrow-up-right
    Retina Mode
    the example herearrow-up-right
    RichAttributionWidget
    hashtag
    Layers

    Interactive maps are often formed from multiple layers of data, which can be panned (moved), rotated, and sometimes tilted/pitched, based on the user's gesture input, or another programmatic control.

    hashtag
    Tile Basics

    One type of layer included on every map is known as a tile layer, which displays tiles, square segments of a map.

    When multiple tiles, which are each the same dimensions, are laid out around each other, they give the illusion of one continuous map.

    Tiles can be referenced/identified in a few different ways, such as:

    • Slippy Map Convention (the most popular/common)

    • TMSarrow-up-right (very similar to the Slippy Map Convention)

    • WMSarrow-up-right

    Tiles themselves can be of two types:

    • Raster Each tile is a normal pre-rendered standard image, such as JPG or PNG

    • Vector Each tile is a special format containing the data for the tile, and is then rendered by the end library

    This library/documentation focuses on maps accessible via the Slippy Map Convention, although all are supported.

    This library only supports raster tiles. See Raster vs Vector Tiles for more information.

    hashtag
    Slippy Map Convention

    circle-info

    For more information about the Slippy Map Convention, visit the OpenStreetMap Wikiarrow-up-right.

    Slippy map tiles are accessed by 3 coordinates, x/y/z.

    X & Y coordinates correspond to all the latitudes and longitudes contained within that tile, however they are not actual longitude and latitude. For example, geographic coordinate (61.127, -0.123) might be in the tile (128983, 430239).

    The Z value represents the current zoom level, where one tile (0/0/0arrow-up-right) covers the entire planet with extremely low detail at level 0, to level 20 (although some tile servers will support even higher zoom levels) where over 1 trillion tiles are required to cover the entire surface of the Earth.

    hashtag
    Sourcing Tiles

    Tiles, especially raster tiles, take a lot of computing power and time to generate, because of the massive scale of all the input and output data. Therefore, most tiles are sourced externally, from an online tile server (either publicly or by users holding an API key), or sometimes from the local filesystem or asset store of the app.

    hashtag
    Tile Providers

    A tile provider (within flutter_map) is responsible for:

    • Constructing the path/URL to a tile, when given its coordinates (x/y/z): Slippy Map Convention

    • Using an ImageProvider or other mechanism to fetch that tile: Sourcing Tiles

    • Performing any other processing steps, such as caching

    But don't worry! flutter_map (or a plugin) creates a provider for you, so for most use cases and tile sources, you shouldn't need to handle this yourself!

    circle-info

    This can be quite confusing for newcomers!

    Within this library, 'tile providers' use 'tile servers' to retrieve tiles from the Internet. On the other hand, 'tile servers' and external sites usually use 'tile providers' to mean 'tile servers'!

    https://youtu.be/3mHC-Pf8-dUarrow-up-right
    https://youtu.be/jtBV3GgQLg8arrow-up-right
    Other Optionschevron-right
    Tile Providerschevron-right
    widget, use
    MapController.of(context)
    .
    circle-info

    Calling this method in a build method will cause the widget to automatically rebuild if the MapController changes. See Creating New Layers for more information.

    If this throws a StateError, try wrapping the concerned widget in a Builder, to ensure the FlutterMap widget is parenting the BuildContext. If this has no effect, use Usage Outside Of FlutterMap instead.

    hashtag
    Usage Outside Of FlutterMap

    hashtag
    Initialisation

    To use a MapController, it must initialised like any other object and then passed to the FlutterMap. This attaches them until the map is disposed.

    hashtag
    Usage Inside initState()

    Sometimes, it is necessary MapController in initState() before the map has been built, for example to attach an event listener (Listen To Events). This is not directly possible, as the map must be built for the controller to be attached.

    Instead, use the MapOptions.onMapReady callback. The initialised MapController can be used freely within it.

    circle-exclamation

    MapController methods that change the position of the map should not be used instantly in onMapReady - see issue #1507arrow-up-right.

    Using them as a reaction to a map event is still fine.

    hashtag
    Animated Movements

    Whilst animated movements through MapControllers aren't built-in, the community maintained plugin flutter_map_animationsarrow-up-right provides this, and much more!

    The example application also includes a page demonstrating a custom animated map movement without the plugin.

    MapCamera

    Bundling Provide a set of tiles to all users through assets or the filesystem

    hashtag
    Caching

    There's 3 methods that basic caching can be implemented in your app, two of which rely on community maintained plugins:

    1. flutter_map_cachearrow-up-right (lightweight and MIT licensed)

    2. flutter_map_tile_cachingarrow-up-right (also includes Bulk Downloading, but GPL licensed)

    3. Custom implementation, via a custom TileProvider and ImageProvider (either custom or via a package such as cached_network_imagearrow-up-right)

    hashtag
    Bulk Downloading

    When it comes to bulk downloading, this is much more complex than Caching, especially for regions that are a non-rectangular shape. Implementing this can be very time consuming and prone to issues.

    The community maintained plugin 'flutter_map_tile_caching'arrow-up-right includes advanced bulk downloading functionality, of multiple different region shapes, and other functionality. It is however GPL licensed. To help choose whether FMTC or DIY is more appropriate for your use case, please see:

    hashtag
    Bundled Map Tiles

    If you have a set of custom raster tiles that you need to provide to all your users, you may want to consider bundling them together, to make a them easier to deploy to your users.

    There is essentially two options for doing this:

    • Using AssetTileProvider, you can bundle a set of map tiles and register them as an asset within your app's pubspec.yaml. This means that they will be downloaded together with your application, keeping setup simple, but at the expense of a larger application bundle size.

    • Using FileTileProvider, you can bundle a set of map tiles and store them on a remote web server, that can be downloaded from later. This means that the setup may be more complicated for users, but the application's bundle size will be much smaller.

    Either way, the filesystem should be structured like this: 'offlineMap/{z}/{x}/{y}.png', where every .png image is a tile.

    If you have a raster-format .mbtiles file, for example from TileMill, you should use mbtilesToPngsarrow-up-right to convert it to the correct structure first. Alternatively, you can use an external package such as 'flutter_mbtiles_extractorarrow-up-right' to extract during runtime.

    Caching
    Bulk downloading
    found herearrow-up-right
    Closed RichAttributionWidget
    Opened RichAttributionWidget, as in the example app
    SimpleAttributionWidget, as in the example app
    popular mapping librariesarrow-up-right
    An example Marker, using FlutterLogo as the child
    stars
    pub.dev
    Open PRs

    Tile Providers

    The tileProvider parameter in TileLayer takes a TileProvider object specifying a tile provider to use for that layer.

    This has a default of NetworkTileProvider which gets tiles from the internet through a dedicated image provider.

    There's two situations in which you'll need to change the tile provider:

    • Sourcing tiles from the filesystem or asset store:

    • Using a that instructs you to do so ()

    hashtag
    Network Tile Providers

    These tile providers use the urlTemplate to get the appropriate tile from the a network, usually the World Wide Web.

    The underlying custom ImageProviders will cache tiles in memory, so that they do not require another request to the tile server if they are pruned then re-loaded. This should result in them being loaded quicker, as well as enabling already loaded tiles to appear even without Internet connection (at least in the same session).

    circle-exclamation

    Specifying any fallbackUrl (even if it is not used) in the TileLayer will prevent loaded tiles from being cached in memory.

    This is to avoid issues where the urlTemplate is flaky (sometimes works, sometimes doesn't), to prevent potentially different tilesets being displayed at the same time.

    hashtag
    NetworkTileProvider

    This is the default tile provider, and does nothing particularly special. It takes two arguments, but you'll usually never need to specify them:

    • httpClient: BaseClient By default, a RetryClient backed by a standard Client is used

    • headers: Map<String, String>

    hashtag

    circle-info

    This requires the '' plugin to be installed.

    This plugin is part of the official 'flutter_map' organisation, and maintained by the same maintainers.

    Tiles that are removed/pruned before they are fully loaded do not need to complete (down)loading, and therefore do not need to complete the HTTP interaction. Cancelling these unnecessary tile requests early could:

    • Reduce tile loading durations (particularly on the web)

    • Reduce users' (cellular) data and cache space consumption

    • Reduce costly tile requests to tile servers*

    This provider uses '', which supports aborting unnecessary HTTP requests in-flight, after they have already been sent.

    Although HTTP request abortion is supported on all platforms, it is especially useful on the web - and therefore recommended for web apps. This is because the web platform has a limited number of simulatous HTTP requests, and so closing the requests allows new requests to be made for new tiles. On other platforms, the other benefits may still occur, but may not be as visible as on the web.

    Once HTTP request abortion is , NetworkTileProvider will be updated to take advantage of it, replacing and deprecating this provider. This tile provider is currently a separate package and not the default due to the reliance on the additional Dio dependency.

    hashtag
    Local Tile Providers

    These tile providers use the urlTemplate to get the appropriate tile from the asset store of the application, or from a file on the users device, respectively.

    circle-exclamation

    Specifying any fallbackUrl (even if it is not used) in the TileLayer will reduce the performance of these providers.

    It will cause with AssetTileProvider, and will cause main thread blocking when requesting tiles from FileTileProvider.

    hashtag
    AssetTileProvider

    This tile providers uses the templateUrl to get the appropriate tile from the asset store of the application.

    circle-info

    Asset management in Flutter leaves a lot to be desired! Unfortunately, every single sub-directory (to the level of tiles) must be listed.

    hashtag
    FileTileProvider

    This tile providers uses the templateUrl to get the appropriate tile from the a path/directory/file on the user's device - either internal application storage or external storage.

    circle-exclamation

    On the web, FileTileProvider() will throw an UnsupportedError when a tile request is attempted, due to the lack of the web platform's access to the local filesystem.

    If you know you are running on the web platform, use a or a custom tile provider.

    hashtag
    Offline Mapping

    Unexpected error with integration github-files: Integration is not installed on this space

    Options

    To dictate & restrict what the map can and should do, regardless of its contents, it needs some guidance!

    It provides options that can be categorized into three main parts:

    • Defines the location of the map when it is first loaded

    • Defines restrictions that last throughout the map's lifetime

    final mapController = MapController();
    
    @override
    Widget build(BuildContext context) =>
        FlutterMap(
            mapController: mapController,
            // ...
        );
    final mapController = MapController();
    
    @override
    Widget build(BuildContext context) =>
        FlutterMap(
            mapController: mapController,
            options: MapOptions(
                onMapReady: () {
                    mapController.mapEventStream.listen((evt) {});
                    // And any other `MapController` dependent non-movement methods
                },
            ),
        );
    children: [
      RichAttributionWidget(
        animationConfig: const ScaleRAWA(), // Or `FadeRAWA` as is default
        attributions: [
          TextSourceAttribution(
            'OpenStreetMap contributors',
            onTap: () => launchUrl(Uri.parse('https://openstreetmap.org/copyright')),
          ),
        ],
      ),
    ],
    children: [
      SimpleAttributionWidget(
        source: Text('OpenStreetMap contributors'),
      ),
    ],
    MarkerLayer(
      markers: [
        Marker(
          point: LatLng(30, 40),
          width: 80,
          height: 80,
          child: FlutterLogo(),
        ),
      ],
    ),
    WMTSarrow-up-right
    Retina Mode
    By default, only headers sent by the platform are included with each request, plus an overridden (where possible) 'User-Agent' header based on the
    property
    Improve performance by reducing CPU and IO work
    plugin
    Creating New Tile Providers
    CancellableNetworkTileProviderarrow-up-right
    flutter_map_cancellable_tile_providerarrow-up-right
    dioarrow-up-right
    added to Dart's 'native' 'http' package (which already has a PR opened)arrow-up-right
    23% slower asset tile requestsarrow-up-right
    NetworkTileProvider
    Offline Mappingchevron-right
    Local Tile Providers
    userAgentPackageName
    likes
    Routing/Navigation
    Open Issues
  • Event handling Defines methods that are called on specific map events

  • hashtag
    Initial Positioning

    circle-info

    Changing these properties after the map has already been built for the first time will have no effect: they only apply on initialisation.

    To control the map programatically, use a MapController: Control Camera.

    One part of MapOptions responsibilities is to define how the map should be positioned when first loaded. There's two ways to do this (that are incompatible):

    • initialCenter (LatLng) & initialZoom

    • initialCameraFit

      • by bounds (circumscribed): CameraFit.bounds

      • by bounds (inscribed): CameraFit.insideBounds

      • by coordinates (circumscribed): CameraFit.coordinates

    It is possible to also set the map's initialRotation in degrees, if you don't want it North (0°) facing initially.

    If rotation is enabled/allowed, if using initialCameraFit, prefer defining it by coordinates for a more intended/tight fit.

    hashtag
    Permanent Rules

    One part of MapOptions responsibilities is to define the restrictions and limitations of the map and what users can/cannot do with it.

    Some of the options are described elsewhere in this documentation, in context. In addition, the API docs show all the available options, and below is a partial list of options:

    • cameraConstraint

      • camera bounds inside bounds: CameraConstraint.bounds

      • camera center inside bounds: CameraConstraint.center

      • unconstrained (default): CameraConstraint.unconstrained

    • maxZoom and minZoom Sets a hard limit on the maximum and minimum amounts that the map can be zoomed

    • Configures the gestures that the user can use to interact with the map - for example, disable rotation or configure cursor/keyboard rotation

    circle-check

    Instead of maxZoom (or in addition to), consider setting maxNativeZoom per TileLayer instead, to allow tiles to scale (and lose quality) on the final zoom level, instead of setting a hard limit.

    Initial positioning
    Permanent rules
    CircleMarker class - flutter_map library - Dart APIpub.devchevron-right
    CircleLayer class - flutter_map library - Dart APIpub.devchevron-right

    Polyline Layer

    You can add lines to maps by making them out of individual coordinates using PolylineLayer and Polylines.

    An example Polyline

    hashtag
    Performance Recommendations

    Excessive use of polylines may create performance issues. There are two options to attempt to improve performance.

    circle-check

    We're working on improvements right now to make your app even more buttery smooth! Stay up to date with the latest performance improvements by joining our Discord server.

    hashtag
    Sticking With PolylineLayer

    It is easiest to try to squeeze as much performance out of Polylines as possible. However, this may not always be the best option.

    Consider using both of the methods below:

    • Split long lines into individual Polylines at regular intervals, then enable polylineCulling, in order to prevent the calculation and rendering of Polylines outside of the current viewport.

    • Simplify the polyline by reducing the number of points within it, in order to reduce raster and calculation times. It is recommended to do this to varying degrees and resolutions based on the current zoom level. It may be possible to use an external Flutter library called .

    The first method will improve performance when zoomed in, as more Polylines will be able to be culled, whilst the second method will improve performance when zoomed out, without impacting visuals (when done well).

    hashtag
    Using A Separate TileLayer

    If using PolylineLayer as above still does not reach satisfactory performance, then the best option may be to render a custom tile set. For example, this may be necessary when attempting to draw a number of long-distance routes, or other widespread dataset.

    circle-info

    We're unable to provide support with this method, and this may become outdated.

    The first step is to render the desired lines into a tileset with a transparent background - is commonly used to do this, and generates vector-format MBTiles.

    If you have raster tiles, you're all set to serve as normal/as you choose. More commonly though, you'll have vector tiles at this step, as with 'tippecanoe', so you'll need to do one of the following things:

    • Try to convert it to raster tiles all in one shot, and if necessary, use a tool like to extract the raster .mbtiles into a slippy map tree

    • Give the MBTiles/vector tiles to the vector map plugin

    • Serve the tiles via something like , which provides an on-the-fly rasterizer

    If you have raster tiles, you're all set to serve as normal.

    To provide the tiles to the users within flutter_map, see .

    hashtag
    Routing/Navigation

    Routing is out of scope for 'flutter_map'. However, if you can get a list of coordinates from a 3rd party, then you can use polylines to show them!

    Good open source options that can be self-hosted include (which includes a public demo server) and . You can also use a commercial solution such as Mapbox or Google Maps - these can often give more accurate/preferable results because they can use their traffic data when routing.

    hashtag
    Converting Formats

    You may have a polyline with 'Google Polyline Encoding' (which is a lossy compression algorithm to convert coordinates into a string and back). These are often returned from routing engines, for example. In this case, you'll need to decode the polyline to the correct format first, before you can use it in a Polyline's points argument.

    One way to accomplish this is to use another Flutter library called , together with a custom method. You can use the code snippet below, which can just be pasted into a file and imported whenever needed:

    You can then use the package and the above snippet by doing:

    Tile Layer

    The basis of any map is a TileLayer, which displays square raster images in a continuous grid, sourced from the Internet or a local file system.

    flutter_map supports WMS Usage, but most map tiles are accessed through Slippy Map/CARTO/XYZ URLs.

    circle-exclamation

    You must comply with the appropriate restrictions and terms of service set by your tile server. Failure to do so may lead to any punishment, at the tile server's discretion.

    This library and/or the creator(s) are not responsible for any violations you make using this package.

    The OpenStreetMap Tile Server (as used above) ToS can be . Other servers may have different terms.

    hashtag
    URL Template

    circle-check

    This parameter must be specified unless is specified.

    The URL template is a string that contains placeholders, which, when filled in, create a URL/URI to a specific tile.

    Specifically, flutter_map supports the Slippy Map format, sometimes referred to as CARTO or Raster XYZ. Tiles are referred to by their zoom level, and position on the X & Y axis. For more information, read .

    These templates are usually documented by your tile server, and will always include the following placeholders:

    • {x}: x axis coordinate

    • {y}: y axis coordinate

    • {z}

    Sometimes, they also include:

    • {s}:

    • {r}:

    Additional placeholders can also be added freely to the template, and are filled in with the specified values in additionalOptions. This can be used to easier add switchable styles or access tokens, for example.

    hashtag
    Subdomains

    Some tile servers provide mirrors/redirects of the main tile server on/via subdomains, such as 'a', 'b', 'c'.

    These were necessary to bypass browsers' limitations on simultaneous HTTP connections, thus increasing the number of tiles that can load at once.

    To use subdomains, add the {s} placeholder, and specify the available subdomains in TileLayer.subdomains. flutter_map will then fill the placeholder with one of these values based on internal logic.

    circle-exclamation

    Subdomains are now usually due to the usage of HTTP/2 & HTTP/3 which don't have the same restrictions.

    Usage of subdomains will also hinder Flutter's ability to cache tiles, potentially leading to increased tile requests and costs.

    If the server supports HTTP/2 or HTTP/3 (), avoid using subdomains.

    hashtag
    Retina Mode

    Retina mode improves the resolution of map tiles, an effect particularly visible on high density displays.

    Raster map tiles can look pixelated (especially on high density displays), so some servers support , which are tiles at twice the resolution of normal tiles. However, not all tile servers support this, so flutter_map can simulate retina behaviour.

    It is recommended to enable retina mode on high density displays (especially where the server natively supports retina tiles). This can be done by calling RetinaMode.isHighDensity with the current BuildContext, and passing the result to TileLayer.retinaMode.

    If the {r} placeholder is present in the the urlTemplate, and retinaMode is enabled, then it will be filled with "@2x". If it is not present, but retinaMode is enabled, then flutter_map will simulate retina behaviour by requesting four tiles at a larger zoom level and combining them together in place of one.

    circle-exclamation

    Note that simulating retina mode will increase tile requests, decrease the effective maximum zoom by 1, and may result in map labels/text/POIs appearing smaller than normal.

    Always prefer the server's native retina tiles where available.

    hashtag
    Fallback URL Template

    It's also possible to specify a fallbackUrl template, used if fetching a tile from the primary urlTemplate fails (which has the same format as this).

    circle-exclamation

    Specifying a fallbackUrl does have negative effects on performance and efficiency. Avoid specifying fallbackUrl unless absolutely necessary for your use case.

    See in-code documentation and for more information.

    hashtag
    userAgentPackageName

    circle-check

    Although it is programatically optional, always specify the userAgentPackageName argument to avoid being blocked by your tile server.

    This parameter should be passed the application's package name, such as 'com.example.app'. This is important to avoid blocking by tile servers due to high-levels of unidentified traffic. If no value is passed, it defaults to 'unknown'.

    This is then formatted into a 'User-Agent' header, and appended to the TileProvider's headers map, if it is not already present.

    This is ignored on the web, where the 'User-Agent' header cannot be changed due to a limitation of Dart/browsers.

    hashtag
    Tile Providers

    circle-check

    If a large proportion of your users use the web platform, it is preferable to use CancellableNetworkTileProvider, instead of the default NetworkTileProvider. It may also be beneficial to use this tile provider on other platforms as well.

    See for more information.

    Need more control over how the URL template is interpreted and/or tiles are fetched? You'll need to change the TileProvider.

    Using Bing Maps

    circle-info

    'flutter_map' is in no way associated or related with Bing Maps.

    Bing Maps' home page: microsoft.com/mapsarrow-up-right

    To display map tiles from Bing Maps, a little more effort is needed, as they use a RESTful API with quadkeys, rather than the standard slippy map system.

    Luckily, we've constructed all the code you should need below! Feel free to copy and paste into your projects.

    circle-info

    Thanks to for discovering the .

    circle-exclamation

    Attribution is not demonstrated here, but may be required. Ensure you comply with Bing Maps' ToS.

    flutter_map - Thunderforestwww.thunderforest.comchevron-right
    Visit our documentation over on Thunderforest's site (may be outdated)
    Providers - Switch2OSMswitch2osm.orgchevron-right
    Raster tile providers - OpenStreetMap Wikiwiki.openstreetmap.orgchevron-right
    Serving your own tiles - Switch2OSMswitch2osm.orgchevron-right
    flutter_map Demodemo.fleaflet.devchevron-right
    nightly.link | Repository fleaflet/flutter_map | Workflow master.yml | Branch masternightly.linkchevron-right
    Latest Build Artifacts (thanks nightlyarrow-up-right)
    MapCamera class - flutter_map library - Dart APIpub.devchevron-right
    BaseOverlayImage class - flutter_map library - Dart APIpub.devchevron-right
    OverlayImageLayer class - flutter_map library - Dart APIpub.devchevron-right
    InteractionOptions class - flutter_map library - Dart APIpub.devchevron-right
    Polygon class - flutter_map library - Dart APIpub.devchevron-right
    PolygonLayer class - flutter_map library - Dart APIpub.devchevron-right
    [FEATURE] Interactive `Polygon`s · Issue #385 · fleaflet/flutter_mapGitHubchevron-right

    Creating New Tile Providers

    One common requirement is a custom TileProvider, and potentially a custom ImageProvider inside. This will allow your plugin to intercept all tile requests made by a map, and take your own action(s), before finally returning a tile.

    circle-info

    Check the for providers that already implement the behaviour you wish to replicate.

    WMSTileLayerOptions class - flutter_map library - Dart APIpub.devchevron-right
    PolylineLayer(
      polylines: [
        Polyline(
          points: [LatLng(30, 40), LatLng(20, 50), LatLng(25, 45)],
          color: Colors.blue,
        ),
      ],
    ),
    TileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      userAgentPackageName: 'dev.fleaflet.flutter_map.example',
      // Plenty of other options available!
    ),
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo
    Luka Glušicaarrow-up-right
    basic initial implementationarrow-up-right
    hashtag
    1. Extending TileProvider

    To create your own usable TileProvider, the first step is making a class that extends the abstract class, and adding a constructor.

    The constructor should accept an argument of super.headers, without a constant default.

    circle-info

    If using an object that needs closing/cancelling, such as an HttpClient, override the dispose method.

    hashtag
    2. Setup Tile Retrieval

    TileProviders must implement a method to return an ImageProvider (the image of a tile), given its coordinates and the TileLayer it is used within.

    circle-check

    It is best to put as much logic as possible into a custom ImageProvider, to avoid blocking the main thread.

    There's two methods that could be called by flutter_map internals to retrieve a tile: getImage or getImageWithCancelLoadingSupport.

    Prefer overriding getImageWithCancelLoadingSupport for TileProviders that can cancel the loading of a tile in-flight, if the tile is pruned before it is fully loaded. An example of a provider that may be able to do this is one that makes HTTP requests, as HTTP requests can be aborted on the web (although Dart does not 'natively' support it yet, so a library such as Dio is necessary). Otherwise, getImage must be overridden.

    In addition to the coordinates and TileLayer, the method also takes a Future<void> that is completed when the tile is pruned. It should be listened to for completion (for example, with then), then used to trigger the cancellation.

    For an example of this, see CancellableNetworkTileProvider.

    circle-info

    If developing a plugin, you may wish to adjust the 'User-Agent' header has been to further differentiate your plugin's traffic from vanilla 'flutter_map' traffic.

    hashtag
    (Optionally) Override URL Generation

    Some custom TileProviders may want to change the way URLs are generated for tiles, given a coordinate.

    It's possible to override:

    • how the urlTemplate's placeholders are populated: populateTemplatePlaceholders

    • the values used to populate those placeholders: generateReplacementMap

    • the generation method itself: getTileUrl and/or getTileFallbackUrl

    circle-exclamation

    Avoid overriding the generation method itself, as it is not usually necessary.

    Plugins List
    bing_maps.dart
    // All compatible imagery sets
    enum BingMapsImagerySet {
      road('RoadOnDemand', zoomBounds: (min: 0, max: 21)),
      aerial('Aerial', zoomBounds: (min: 0, max: 20)),
      aerialLabels('AerialWithLabelsOnDemand', zoomBounds: (min: 0, max: 20)),
      canvasDark('CanvasDark', zoomBounds: (min: 0, max: 21)),
      canvasLight('CanvasLight', zoomBounds: (min: 0, max: 21)),
      canvasGray('CanvasGray', zoomBounds: (min: 0, max: 21)),
      ordnanceSurvey('OrdnanceSurvey', zoomBounds: (min: 12, max: 17));
    
      final String urlValue;
      final ({int min, int max}) zoomBounds;
    
      const BingMapsImagerySet(this.urlValue, {required this.zoomBounds});
    }
    
    // Custom tile provider that contains the quadkeys logic
    // Note that you can also extend from the CancellableNetworkTileProvider
    class BingMapsTileProvider extends NetworkTileProvider {
      BingMapsTileProvider({super.headers});
    
      String _getQuadKey(int x, int y, int z) {
        final quadKey = StringBuffer();
        for (int i = z; i > 0; i--) {
          int digit = 0;
          final int mask = 1 << (i - 1);
          if ((x & mask) != 0) digit++;
          if ((y & mask) != 0) digit += 2;
          quadKey.write(digit);
        }
        return quadKey.toString();
      }
    
      @override
      Map<String, String> generateReplacementMap(
        String urlTemplate,
        TileCoordinates coordinates,
        TileLayer options,
      ) =>
          super.generateReplacementMap(urlTemplate, coordinates, options)
            ..addAll(
              {
                'culture': 'en-GB', // Or your culture value of choice
                'subdomain': options.subdomains[
                    (coordinates.x + coordinates.y) % options.subdomains.length],
                'quadkey': _getQuadKey(coordinates.x, coordinates.y, coordinates.z),
              },
            );
    }
    
    // Custom `TileLayer` wrapper that can be inserted into a `FlutterMap`
    class BingMapsTileLayer extends StatelessWidget {
      const BingMapsTileLayer({
        super.key,
        required this.apiKey,
        required this.imagerySet,
      });
    
      final String apiKey;
      final BingMapsImagerySet imagerySet;
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: http.get(
            Uri.parse(
              'http://dev.virtualearth.net/REST/V1/Imagery/Metadata/${imagerySet.urlValue}?output=json&include=ImageryProviders&key=$apiKey',
            ),
          ),
          builder: (context, response) {
            if (response.data == null) return const Placeholder();
    
            return TileLayer(
              urlTemplate: (((((jsonDecode(response.data!.body)
                              as Map<String, dynamic>)['resourceSets']
                          as List<dynamic>)[0] as Map<String, dynamic>)['resources']
                      as List<dynamic>)[0] as Map<String, dynamic>)['imageUrl']
                  as String,
              tileProvider: BingMapsTileProvider(),
              subdomains: const ['t0', 't1', 't2', 't3'],
              minNativeZoom: imagerySet.zoomBounds.min,
              maxNativeZoom: imagerySet.zoomBounds.max,
            );
          },
        );
      }
    }
        @override
        bool get supportsCancelLoading => true;
        
        @override
        ImageProvider getImageWithCancelLoadingSupport(
            TileCoordinates coordinates,
            TileLayer options,
            Future<void> cancelLoading,
        ) =>
            CustomCancellableImageProvider(
                url: getTileUrl(coordinates, options),
                fallbackUrl: getTileFallbackUrl(coordinates, options),
                cancelLoading: cancelLoading,
                tileProvider: this,
            );
        @override
        ImageProvider getImage(TileCoordinates coordinates, TileLayer options) =>
            CustomImageProvider(
                url: getTileUrl(coordinates, options),
                fallbackUrl: getTileFallbackUrl(coordinates, options),
                tileProvider: this,
            );
    class CustomTileProvider extends TileProvider {
        CustomTileProvider({
            // Suitably initialise your own custom properties
            super.headers, // Accept a `Map` of custom HTTP headers
        })
    }
    : zoom level
    found herearrow-up-right
    wmsOptions
    How Does It Work?
    considered redundantarrow-up-right
    how to checkarrow-up-right
    high-resolution "@2x" tilesarrow-up-right
    Tile Providers
    Tile Providerschevron-right
    Subdomains
    Retina Mode
    CancellableNetworkTileProvider
    simplifyarrow-up-right
    tippecanoearrow-up-right
    mbtilesToPngsarrow-up-right
    tileserver-glarrow-up-right
    Tile Providers
    OSRMarrow-up-right
    Valhallaarrow-up-right
    'google_polyline_algorithm'arrow-up-right
    interactionOptions
    Logo
    Logo
    Logo
    CursorKeyboardRotationOptions class - flutter_map library - Dart APIpub.devchevron-right
    Logo
    Logo
    An icon and a button displayed over a map, in the bottom right corner
    A white box with attribution text displayed over a map
    RichAttributionWidget class - flutter_map library - Dart APIpub.devchevron-right
    SimpleAttributionWidget class - flutter_map library - Dart APIpub.devchevron-right
    MarkerLayer class - flutter_map library - Dart APIpub.devchevron-right
    Marker Clustering
    Marker class - flutter_map library - Dart APIpub.devchevron-right

    Plugins List

    There are many independently maintained 'plugins' created by the 'flutter_map' community that give extra, prebuilt functionality, saving you even more time and potentially money.

    Some pages in this documentation provide direct links to these plugins to make it easier for you to find a suitable plugin.

    However, if you're just browsing, a full list is provided below (in no particular order), containing many of the available plugins. You can click on any of the tiles to visit its GitHub repo or pub.dev package.

    triangle-exclamation

    Although these plugins have been checked by 'flutter_map' maintainers, we do not accept responsibility for any issues or threats posed by independently maintained plugins.

    MapController class - flutter_map library - Dart APIpub.devchevron-right
    Is FMTC Right For Me? | FMTC Docsfmtc.jaffaketchup.devchevron-right
    unpack_polyline.dart
    import 'package:latlong2/latlong.dart';
    export 'package:google_polyline_algorithm/google_polyline_algorithm.dart'
        show decodePolyline;
    
    extension PolylineExt on List<List<num>> {
      List<LatLng> unpackPolyline() =>
          map((p) => LatLng(p[0].toDouble(), p[1].toDouble())).toList();
    }
    import 'unpack_polyline.dart';
    
    decodePolyline('<encoded-polyline>').unpackPolyline(); // Returns `List<LatLng>` for a map polyline
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo
    Logo

    Use plugins at your own risk.

    circle-exclamation

    There is no guarantee that any of these plugins will support the latest version of flutter_map. Please remain patient with the plugin authors/owners.

    circle-info

    Many plugins provide multiple methods to achieve similar goals. It is recommended to read the documentation of each potential plugin before using it in your project, as they might have slightly different feature sets or stability.

    hashtag
    Tools

    hashtag
    External

    These are not necessarily purpose built for flutter_map, but could be very useful for some applications for related purposes.

    hashtag
    Additional Layers

    hashtag
    Offline Mapping

    To help choose between one of these plugins or a DIY solution, see:

    hashtag
    Better Markers

    hashtag
    Marker Clustering

    hashtag
    Better Polylines & Polygons

    Offline Mappingchevron-right

    Migrating To v6

    circle-info

    This update has renewed two of the oldest surviving sections of 'flutter_map' (state/MapController and TileProviders), fixed bugs, and added features!

    This is significant progress in our aim to renew the project and bring it up to date. In the long run, this will bring it inline with up-to-date Flutter good practises and techniques, improve its performance and stability, and reduce the maintenance burden.

    There are major breaking changes for all users, as well as some things users should check and possibly change.

    Some changes have deprecations and messages, some do not. Please refer to the sections below for information on how to migrate your project, as well as in-code documentation and deprecation messages, if your migration is not listed below. Some changes are omitted if they are deemed unlikely to affect implementations.

    hashtag
    Changelog & Highlights

    There's loads of changes in this release, which will improve performance and reduce costs! Check out these highlights, along with the full changelog:

    circle-check

    We've added in-memory caching to the underlying custom ImageProvider. This means that they do not need to be re-requested if they are pruned then re-loaded, reducing tile loading times, and reduce tile requests and costs!

    No action is needed to benefit from this.

    circle-check

    If you're developing an app for the web, there's an exciting new performance boost available. By aborting in-flight HTTP requests if tiles are pruned before they are fully-loaded, connections can be freed up, reducing tile loading times, and potentially saving you money!

    There are also advantages for other platforms, although they may not be quite as visible.

    Manual action is required to benefit from this. See for more information.

    circle-check

    Rotation is now supported on desktop! Simply use the CTRL (or equivalent) keyboard key (customizable in MapOptions) and mouse.

    circle-check

    We've added some warning & recommendation logs in-code, that will trigger under certain circumstances. If they trigger, make sure to listen to them to benefit from performance and efficiency improvements!

    hashtag
    Migration Instructions

    hashtag
    General/Misc

    chevron-rightCustomPoint has been replaced by extension methods on Pointhashtag

    are now used to add the required functionality to the standard 'dart:math' Point object.

    To migrate, most cases should just need to replace all occurrences of CustomPoint with Point

    chevron-right"Plugin API" import has been removedhashtag

    This import path was getting increasingly useless and exposing increasingly less features compared to the standard import. It also covered the standard import in the auto-generated DartDoc documentation, as it exported it as well.

    All features that need to be exposed are now exposed through the primary import, and the dedicated plugin import has been removed.

    hashtag
    State Management

    chevron-rightFlutterMapState has been removedhashtag

    FlutterMapState previously represented all of the map's state. However, to improve the maintainability of this library's internals, and to improve performance, it has been removed and replaced with several 'aspects':

    • MapCamera.of

    chevron-rightSome of MapController's responsibilities have been moved to MapCamerahashtag

    MapController now only controls the map's position/viewport/camera. The map's position is now described by MapCamera.

    You should not read camera data directly from a MapController

    hashtag
    Children/Layers

    chevron-rightnonRotatedChildren has been removedhashtag

    The approach to 'mobile' and 'static' layers has been changed. Mobile layers now wrap themselves in a MobileLayerTransformer which uses the inherited state, instead of FlutterMap applying the affects directly to them. Static layers should now ensure they use Align and/or SizedBox.expand.

    chevron-rightCustom layers need to define their behaviourhashtag

    The way custom layers are defined has changed. Mobile/moving layers should now use MobileLayerTransformer at the top of their widget tree.

    For more information, see .

    hashtag
    Tile Layer

    chevron-rightretinaMode behaviour has changedhashtag

    Previously, the retinaMode property enabled/disabled the simulation of retina mode. To request retina tiles from the server, either the {r}placeholder or "@2x" string could be included in the urlTemplate. This behaviour was unclear, did not conform to the norms of other mapping packages, and meant the {r} placeholder was actually redundant.

    chevron-rightbackgroundColor has been replaced by MapOptions.backgroundColorhashtag

    This will simplify the developer experience when using multiple overlaid TileLayers, as Colors.transparent will no longer need to be specified. There is no reason that multiple TileLayers would each need to have a different (non-transparent) background colors, as the layers beneath would be invisible and therefore pointless.

    chevron-righttemplateFunction has been replaced by TileProvider.populateTemplatePlaceholdershashtag

    TileProvider.templateFunction has been deprecated. It is now preferrable to create a custom TileProvider extension, and override the populateTemplatePlaceholders method. This has been done to reduce the scope of TileLayer.

    hashtag
    Marker Layer

    chevron-rightanchor and all related objects have been removedhashtag

    In order to simplify Markers, the anchor property and AnchorPos/Anchor objects have been removed without replacement.

    Marker alignment is now performed with the standard Alignment

    chevron-rightrotateOrigin and rotateAligment have been removedhashtag

    These properties on Marker have been removed as it is not apparent what any valid use-case could be, and removing them helped simplify the internals significantly.

    If these are currently used, try changing alignment, and if that does not give the desired results, use a Transform

    chevron-rightMarker.builder has been replaced by childhashtag

    This has been done since using the builder pattern offered no significant advantage.

    To migrate, simply change to using the child parameter, and use as you would any other widget. If a builder is required, for example to access the inherited states (), use the Builder widget yourself.

    hashtag
    Map Options

    chevron-rightcenter, bounds, zoom, and rotation have been replaced with initialCenter, initialCameraFit, initialZoom, and initialRotationhashtag

    chevron-rightmaxBounds has been replaced with cameraConstrainthashtag

    This is part of to better fit the change into using a documented 'camera' and increasing customizability.

    To migrate, rename the properties, and also check the in-code documentation and new objects for information.

    chevron-rightInteractive options (such as interactiveFlags) have been moved into InteractionOptionshashtag

    This has been done to improve readability and seperation of responsibilities.

    For more information, see .

    hashtag
    Tile Providers

    chevron-rightImplementations should switch to extensionshashtag

    It is not recommended to implement TileProvider, as there are now two methods of which only one should be implemented (getImage & getImageWithCancelLoadingSupport), as well as other members that should not usually be overridden.

    To migrate, use extends instead of implements

    chevron-rightExtensions should not provide a constant default value for headers in the constructorhashtag

    TileLayer behaviour has been modified so that the 'User-Agent' header can be set without copying all user-specified headers. It is now inserted into the Map, so it must be immutable/non-constant.

    Note that the headers

    chevron-rightExtensions overriding getTileUrl should consider overriding other methods insteadhashtag

    The logic previously handled by getTileUrl, invertY, and getSubdomain has been refactored into generateReplacementMap, populateTemplatePlaceholders, and getTileUrl

    chevron-rightExtensions implementing getImage should consider overriding getImageWithCancelLoadingSupport instead hashtag

    The framework necessary to support tile providers that can abort in-flight HTTP requests and other processing is now available. For more information about the advantages of cancelling unnecessary tile requests when they are pruned before being fully loaded, see .

    If it is not possible to cancel the loading of a tile, or there is no advantage gained by doing so, you can ignore this.

    Logo
    .
    : for more information, see
  • MapOptions.of: use to access the ambient configured MapOptions

  • (MapController.of): use to access the ambient MapController, even if one was not explicitly defined by the user

  • In most cases, migrating will entail replacing FlutterMapState with MapCamera, but another aspect may be required.

    See and for more information.

    : these methods have been deprecated.

    There are multiple possibilities for migration:

    1. If inside the FlutterMap context, prefer using MapCamera.of(context)

    2. Otherwise, use MapController in the same way, but use the .camera getter to retrieve the MapCamera.

    See for more information.

    This has been done to simplify setup, and allow for placing static layers between mobile layers.
    Now, retinaMode also affects whether the {r} placeholder is filled in. If true, and {r} is present, then that will now be filled in to request retina tiles. If the placeholder is not present, only then will flutter_map simulate retina mode.

    Additionally, it is now recommended to use the RetinaMode.isHighDensity method to check whether retinaMode should be enabled.

    For more information, see .

    Therefore, TileLayers now have transparent backgrounds, and the new MapOptions.backgroundColor property sets the background color of the entire map.

    To migrate, move any background colour specified on the bottom-most TileLayer to MapOptions.

    To migrate, see .
    object through the
    alignment
    argument.

    Due to the previously named anchor being confusingly (and perhaps incorrectly) named, migration without behaviour change is possible just by taking the Alignment from inside any AnchorPos and passing it directly to alignment.

    widget yourself.
    These have been renamed for clarity, as well as to better fit the change into using a documented 'camera' and increasing customizability.

    To migrate, rename the properties, and also check the in-code documentation and new objects for information.

    .

    Further panes will refer to implementations that use extends as 'extensions' for clarity, not to be confused with extension methods.

    property is also now
    final
    .

    To migrate, remove the default value for super.headers: it is not necessary.

    .

    To migrate, consider overriding another of those methods, if it is more suitable. This will reduce the amount of code duplicated in your library from flutter_map's implementation.

    To migrate, override supportsCancelLoading to true, implement getImageWithCancelLoadingSupport as appropriate, and remove the implementation of getImage.
    Extension methodsarrow-up-right
    Interaction Options
    CancellableNetworkTileProvider
    Creating New Layers
    CancellableNetworkTileProvider

    flutter_map_animations (TesteurManiak)

    Replacement MapController which provides animated movement alternatives

    flutter_map_geojson (jozes)

    Parse GeoJson data and transform into map features

    BETA geojson_vector_slicer (ibrierley)

    Display GeoJson using sliced vector tiles, and a suite of other tools

    BETA flutter_osrm (JaffaKetchup)

    Query an OSRM-based server to provide routing and other related functionality

    BETA flutter_map_query_osm_features (JaffaKetchup)

    Query OpenStreetMap features within a radius of a point, using the Overpass and OSM APIs

    dart_earcut (JaffaKetchup)

    Performant earclipping triangulation algorithm, ported from the Mapbox project by the same name

    polybool (mohammedX6)

    Suite of tools to operate on polygons, such as union, intersection, and difference

    simplify (bjartebore)

    High-performance 2D/3D polyline simplification

    vector_map_tiles (greensopinion)

    Suite of tools and layers for working with vector maps and associated style files

    flutter_map_polywidget (TimBaumgart)

    Layer that allows any widget to be displayed inside a positioned box, similar to

    fluttermap_heatmap (tprebs)

    Layer that represents multiple data points in a density-to-color relationship

    lat_lon_grid_plugin (matthiasdittmer)

    Layer that shows a grid of latitude longitude lines

    flutter_map_tile_caching (JaffaKetchup)

    Advanced, performant, highly configurable caching & bulk downloading (under a GPL license)

    flutter_map_cache (josxha)

    Lightweight tile caching with support for most storage backends and request cancellation.

    flutter_map_location_marker (tlserver)

    Provides a prebuilt solution to display the user's location and heading/direction

    flutter_map_marker_popup (rorystephenson)

    Provides a prebuilt solution to display a popup above a marker when tapped

    flutter_map_floating_marker_titles (androidseb)

    Enables the display of 'floating' titles over markers

    BETA flutter_map_fast_markers (KanarekApp)

    Improves performance of markers by painting directly onto canvas

    flutter_map_supercluster (rorystephenson)

    Superfast™ marker clustering solution, without animations

    flutter_map_marker_cluster (lpongetti)

    Beautiful and animated marker clustering solution

    flutter_map_radius_cluster (rorystephenson)

    Marker clustering solution with support for async marker searching within a radius

    flutter_map_tappable_polyline (OwnWeb)

    Provides an onTap callback for Polylines

    flutter_map_line_editor (ibrierley)

    Enables better dynamic editing of Polylines and Polygons

    line_animator (ibrierley)

    Interpolates along a set of points, allowing gradual drawing of lines and animating moving markers

    Overlay Image Layer
    Programmatic Control
    Programmatic Control
    Creating New Tile Providers
    Some of MapController's responsibilities have been moved to MapCamera
    Creating New Layers
    Retina Mode
    TileLayer class - flutter_map library - Dart APIpub.devchevron-right
    Polyline class - flutter_map library - Dart APIpub.devchevron-right
    PolylineLayer class - flutter_map library - Dart APIpub.devchevron-right
    Logo
    Logo
    Logo
    Logo
    MapOptions class - flutter_map library - Dart APIpub.devchevron-right
    Logo
    flutter_map/CHANGELOG.md at master · fleaflet/flutter_mapGitHubchevron-right
    Full Changelog
    Logo
    Accessing Aspects Within Descendants
    InteractiveFlag class - flutter_map library - Dart APIpub.devchevron-right
    Logo