> For the complete documentation index, see [llms.txt](https://docs.fleaflet.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fleaflet.dev/layers/marker-layer.md).

# Marker Layer

You can add single point features - including arbitrary widgets - to maps using `MarkerLayer` and `Marker`s.

{% hint style="success" %}
No more image only markers! [Unlike *other* ](https://github.com/flutter/flutter/issues/24213)😉[^1][ popular mapping libraries](https://github.com/flutter/flutter/issues/24213), we allow usage of any widget as the marker.
{% endhint %}

<figure><img src="https://852902308-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSFuYRJZsfLx0EidjdMud%2Fuploads%2FbAf2OvB3xZmDlW0ml8pY%2FMarker%20Demo.png?alt=media&amp;token=3a28caac-2b65-44f8-87e0-a51cbe1c296b" alt=""><figcaption><p>A variety of <code>Marker</code>s on a rotated map</p></figcaption></figure>

{% embed url="<https://pub.dev/documentation/flutter_map/latest/flutter_map/MarkerLayer-class.html>" %}

{% embed url="<https://pub.dev/documentation/flutter_map/latest/flutter_map/Marker-class.html>" %}

```dart
MarkerLayer(
  markers: [
    Marker(
      point: LatLng(30, 40),
      width: 80,
      height: 80,
      child: FlutterLogo(),
    ),
  ],
),
```

{% hint style="warning" %}
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: [Plugins List](/plugins/list.md#marker-clustering).
{% endhint %}

## Size

The `height` and `width` parameters are required to enable the positioning and culling of the markers to work correctly.

The marker child will be sized to these parameters, which default to 30 logical pixels. If the child will change size, set the size to the largest size and control the size of the child within a widget which allows it to be smaller than the constraints set.

## Alignment & Counter-Rotation

By default, the marker's child is centered over the `point`, and will always remain upright relative to the North when the map is rotated.

This can be changed using `alignment` and `rotate`.&#x20;

To keep the child upright relative to the screen (counter-rotate it compared to any map rotation), set `rotate` to `true`.

To change the pivot point for the counter-rotation and the alignment of the child to the `point`, set the `alignment` accordingly.

For example:

```dart
Marker(
    rotate: true,
    alignment: Alignment.topCenter,
    // ...
),
```

These parameters can also be set directly on the `MarkerLayer` to change the default for all of its markers.

{% hint style="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`.
{% endhint %}

## Handling State

Often, marker children do not have their own internal state (they are `StatelessWidget`s). However, some use-cases may require them to be stateful.

{% hint style="warning" %}
Markers are culled when they go offscreen, and the marker child is not built when culled. Therefore, any widget state is lost when culling.

When multiple of the same marker is visible at once, across multiple worlds, the marker child is built multiple times. Therefore, the widget states are not synchronized, and any keys in the child subtree may not be unique.
{% endhint %}

Marker children should not be `StatefulWidget`s, and keys should not be used in the child's tree. Instead, the state should be detached and moved up in the tree, using an inherited approach. For example, a state management package, or Flutter's built-in options like `InheritedWidget` or `ValueNotifier` - remember that `FlutterMap.children` can contain widgets wrapped around layers like this.

Then, some map should be kept linking a unique property of the marker (its `point` could be suitable and easily accessed in most dynamic marker layer systems) to its state. The marker child can then lookup this state.

For example:

{% code expandable="true" %}

```dart
children: [
    // TileLayer(), etc...
    
    MyInheritedStateApproach(
        states: <LatLng, MyMarkerState>{
            LatLng(0, 0): MyMarkerState(),
            // These could be dynamically generated from a source,
            // for example using `Map.fromEntries`
        },
        child: MarkerLayer(
            markers: [
                Marker(
                    point: LatLng(0, 0),
                    child: MyMarker(point: LatLng(0, 0)),
                ),
                // These could be dynamically generated from a source,
                // for example using `List.generate`
            ],
        ),
    ),
],

// ...

class MyMarker extends StatelessWidget {
    const MyMarker({
        super.key,
        required this.point,
    });
    
    final LatLng point;
    
    @override
    Widget build(BuildContext context) {
        final MyMarkerState state = MyInheritedStateApproach.of(context).state[point];
        return GestureDetector(
            onTap: () {},
            child: Text(state.label),
        );
    }
}
```

{% endcode %}

{% hint style="info" %}
The maintainer team is looking into improving the `MarkerLayer` to improve this situation:

* Providing a `keepAlive` option directly on `Marker`s - although this means culled markers still need to be built (although not necessarily painted), which could be expensive compared to the solution above (which requires more boilerplate but should scale better)
* Painting a marker multiple times across worlds while only building it once - although this is fairly complicated, but in combination with the option above could eventually allow the `Marker` size parameters to become unnecessary/optional

Any contributors would be appreciated, although the second point is quite complicated to implement!
{% endhint %}

## Handling Gestures

If you need to, for example, handle taps and presses on your marker's child, it's easy! Just wrap the child in something like a `GestureDetector`, or a button.

If you need to be able to drag the marker, check out the community maintained plugin '[flutter\_map\_dragmarker](https://github.com/ibrierley/flutter_map_dragmarker)'.\
Alternatively if you need more control, build it yourself. Because of the way flutter\_map handles gestures, the [following workaround](https://github.com/fleaflet/flutter_map/issues/1729#issuecomment-3768956345) may be required to allow the marker to capture the necessary gesture events:

> Use a `RawGestureDetector` and custom `PanGestureRecognizer` than declares victory in the [gesture arena](https://docs.flutter.dev/ui/interactivity/gestures#gesture-disambiguation). For example:
>
> {% code expandable="true" %}
>
> ```dart
> class EagerPanGestureRecognizer extends PanGestureRecognizer {
>   @override
>   void handleEvent(PointerEvent event) {
>     // Immediately claim victory for this pointer
>     if (event is PointerMoveEvent) resolve(GestureDisposition.accepted);
>     super.handleEvent(event);
>   }
> }
>
> // Inside your marker's child builder:
>
> final gestures = <Type, GestureRecognizerFactory>{};
> if (onDragStart != null || onDragUpdate != null || onDragEnd != null) {
>   gestures[EagerPanGestureRecognizer] =
>       GestureRecognizerFactoryWithHandlers<EagerPanGestureRecognizer>(
>           EagerPanGestureRecognizer.new,
>           (SingleEagerPanGestureRecognizer instance) {
>     instance.onStart = onDragStart;
>     instance.onUpdate = onDragUpdate;
>     instance.onEnd = onDragEnd;
>   });
> }
>
> return RawGestureDetector(
>   gestures: gestures,
>   child: child,
> );
> ```
>
> {% endcode %}

[^1]: [Google Maps \*wink \*wink](https://github.com/flutter/flutter/issues/24213)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.fleaflet.dev/layers/marker-layer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
