---
title: "How to Add Animated and Interactive Custom Map Markers in Flutter Maps"
published_at: "2021-05-11T11:00:51+00:00"
modified_at: "2026-01-09T08:27:11+00:00"
url: "https://www.syncfusion.com/blogs/post/add-animated-and-interactive-custom-map-markers-in-flutter-maps"
excerpt: "In Maps, markers are a primary tool used to denote locations with precise latitude and longitude coordinates. The Syncfusion Flutter Maps widget has built-in support to add markers on the MapShapeLayer or MapTileLayer. You can use any type of custom..."
taxonomy_category:
  - "Desktop"
  - "Flutter"
  - "Mobile"
  - "Tips and Tricks"
taxonomy_post_tag:
  - "Android"
  - "desktop"
  - "Flutter"
  - "iOS"
  - "Maps"
  - "Mobile"
---

# How to Add Animated and Interactive Custom Map Markers in Flutter Maps

[Vijayakumar Mariappan](https://www.syncfusion.com/blogs/author/vijayakumar-mariappan)

![How to Add Animated and Interactive Custom Map Markers in Flutter Maps](https://www.syncfusion.com/blogs/wp-content/uploads/2021/05/How-to-Add-Animated-and-Interactive-Custom-Map-Markers-in-Flutter-Maps.png)


In Maps, markers are a primary tool used to denote locations with precise latitude and longitude coordinates. The Syncfusion [Flutter Maps](https://www.syncfusion.com/flutter-widgets/flutter-maps)
 widget has built-in support to add markers on the [MapShapeLayer](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeLayer-class.html)
 or [MapTileLayer](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer-class.html)
. You can use any type of custom widget as a marker, or built-in shapes such as circles, diamonds, squares, and triangles.

In this blog, I am going to explain how to add markers and animate them. If you are new to our Flutter Maps widget, please refer to the following blog posts before proceeding:

- [Introducing Flutter Maps Widget](https://www.syncfusion.com/blogs/post/introducing-flutter-maps-widget.aspx)
- [Easily Visualize OpenStreetMaps and Bing Maps in Flutter](https://www.syncfusion.com/blogs/post/easily-visualize-openstreetmaps-and-bing-maps-in-flutter.aspx)

## **Add an animated marker at load time**

To add an animated marker at load time, we have to add an animated widget as a child of [MapMarker](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapMarker-class.html)
 and start the animation in the [initState](https://api.flutter.dev/flutter/widgets/State/initState.html)
.

In the following example, I’ve animated the fourth index marker at load time.

```
class _LoadAnimatableMarkerAtLoadtime extends StatefulWidget {
  @override
  _LoadAnimatableMarkerAtLoadtimeState createState() =>
      _LoadAnimatableMarkerAtLoadtimeState();
}

class _LoadAnimatableMarkerAtLoadtimeState
    extends State<_LoadAnimatableMarkerAtLoadtime>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late CurvedAnimation _animation;
  late Map<String, MapLatLng> _markers;

  int _selectedMarkerIndex = 4;

  @override
  void initState() {
    _controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 750));
    _animation =
        CurvedAnimation(parent: _controller, curve: Curves.easeOutBack);

    _markers = <String, MapLatLng>{
      'Chad': MapLatLng(15.454166, 18.732206),
      'Nigeria': MapLatLng(9.081999, 8.675277),
      'DRC': MapLatLng(-4.038333, 21.758663),
      'CAR': MapLatLng(6.600281, 20.480205),
      'Sudan': MapLatLng(12.862807, 30.217636),
      'Kenya': MapLatLng(0.0236, 37.9062),
      'Zambia': MapLatLng(-10.974129, 30.861397),
      'Egypt': MapLatLng(25.174109, 28.776359),
      'Algeria': MapLatLng(24.276672, 7.308186),
    };
    _controller.repeat(min: 0.15, max: 1.0, reverse: true);
    super.initState();
  }

  @override
  void dispose() {
    _controller.stop();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Load animatable marker at loadtime'),
      ),
      body: MapTileLayer(
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        initialZoomLevel: 3,
        initialFocalLatLng: MapLatLng(2.3104, 16.5581),
        initialMarkersCount: _markers.length,
        markerBuilder: (BuildContext context, int index) {
          final double size = _selectedMarkerIndex == index ? 40 : 25;
          final MapLatLng markerData = _markers.values.elementAt(index);
          final Icon current = Icon(Icons.location_pin, size: size);
          return MapMarker(
            latitude: markerData.latitude,
            longitude: markerData.longitude,
            child: Transform.translate(
              offset: Offset(0.0, -size / 2),
              child: _selectedMarkerIndex == index
                  ? ScaleTransition(
                      alignment: Alignment.bottomCenter,
                      scale: _animation,
                      child: current)
                  : current,
            ),
          );
        },
      ),
    );
  }
}
```

![Adding an Animated Marker During Initial Loading of Flutter Maps](https://www.syncfusion.com/blogs/wp-content/uploads/2021/05/Adding-an-Animated-Marker-During-Initial-Loading-of-Flutter-Maps.gif)

Adding an Animated Marker During Initial Loading of Flutter Maps

## **Adding a marker programmatically**

To add or update markers dynamically, we will need the help of [MapShapeLayerController](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeLayerController-class.html)
 or [MapTileLayerController](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayerController-class.html)
 depending on whether we use [MapShapeLayer](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeLayer-class.html)
 or [MapTileLayer](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer-class.html)
 to include the marker. MapShapeLayerController and MapTileLayerController control the marker collection dynamically by adding, removing, updating, and clearing the markers.

In the following example, we will add a marker dynamically at a precise coordinate by using the [insertMarker](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLayerController/insertMarker.html)
 method of [MapShapeLayerController](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeLayerController-class.html)
. Here, we use the [Icon](https://api.flutter.dev/flutter/widgets/Icon-class.html)
 widget as a marker. Calling the [insertMarker](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLayerController/insertMarker.html)
 method of the MapShapeLayerControl triggers the [TileLayer](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer-class.html)
’s [markerBuilder](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLayer/markerBuilder.html)
 callback with the respective index. Here, we have to return the [MapMarker](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapMarker-class.html)
 to be updated in the current index.

```
class AddingMarkerDynamically extends StatefulWidget {
  @override
  _AddingMarkerDynamicallyState createState() =>
      _AddingMarkerDynamicallyState();
}

class _AddingMarkerDynamicallyState extends State
    with SingleTickerProviderStateMixin {
  late MapTileLayerController _tileLayerController;

  @override
  void initState() {
    _tileLayerController = MapTileLayerController();
    super.initState();
  }

  @override
  void dispose() {
    _tileLayerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add a marker dynamically'),
      ),
      body: MapTileLayer(
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        initialZoomLevel: 3,
        initialFocalLatLng: MapLatLng(2.3104, 16.5581),
        controller: _tileLayerController,
        markerBuilder: (BuildContext context, int index) {
          return MapMarker(
            latitude: 6.6111,
            longitude: 20.9394,
            child: Transform.translate(
              offset: Offset(0.0, -20.0),
              child: Icon(Icons.location_pin, size: 40),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add_location),
        onPressed: () => _tileLayerController.insertMarker(0),
      ),
    );
  }
}
```

![Adding an Animated Marker Dynamically in Flutter Maps](https://www.syncfusion.com/blogs/wp-content/uploads/2021/05/Adding-an-Animated-Marker-Dynamically-in-Flutter-Maps.gif)

Adding an Animated Marker Dynamically in Flutter Maps

## **Animate a marker or group of markers dynamically**

Dynamic marker updates require the help of [MapShapeLayerController](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeLayerController-class.html)
 and [MapTileLayerController](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayerController-class.html)
. The following example demonstrates updating [MapMarker](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapMarker-class.html)
’s child dynamically as an animated widget to start the animation.

In parallel, invoke [updateMarkers](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLayerController/updateMarkers.html)
 with respective marker indices to update the markers.

```
class AnimateGroupOfMarkersDynamically extends StatefulWidget {
  @override
  _AnimateGroupOfMarkersDynamicallyState createState() =>
      _AnimateGroupOfMarkersDynamicallyState();
}

class _AnimateGroupOfMarkersDynamicallyState
    extends State
    with TickerProviderStateMixin {
  late AnimationController _controller;
  late CurvedAnimation _animation;
  late MapTileLayerController _tileLayerController;
  late Map<String, MapLatLng> _markers;

  List _selectedMarkerIndices = [];

  @override
  void initState() {
    _controller = AnimationController(
        vsync: this,
        duration: const Duration(milliseconds: 750),
        reverseDuration: const Duration(milliseconds: 750));
    _animation =
        CurvedAnimation(parent: _controller, curve: Curves.easeOutBack);
    _tileLayerController = MapTileLayerController();

    _markers = <String, MapLatLng>{
      'Chad': MapLatLng(15.454166, 18.732206),
      'Nigeria': MapLatLng(9.081999, 8.675277),
      'DRC': MapLatLng(-4.038333, 21.758663),
      'CAR': MapLatLng(6.600281, 20.480205),
      'Sudan': MapLatLng(12.862807, 30.217636),
      'Kenya': MapLatLng(0.0236, 37.9062),
      'Zambia': MapLatLng(-10.974129, 30.861397),
      'Egypt': MapLatLng(25.174109, 28.776359),
      'Algeria': MapLatLng(24.276672, 7.308186),
    };

    _controller.repeat(min: 0.1, max: 1.0, reverse: true);
    super.initState();
  }

  @override
  void dispose() {
    _controller.stop();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Animate group of markers dynamically')),
      body: MapTileLayer(
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        initialZoomLevel: 3,
        initialFocalLatLng: MapLatLng(2.3104, 16.5581),
        controller: _tileLayerController,
        initialMarkersCount: _markers.length,
        markerBuilder: (BuildContext context, int index) {
          final double size = _selectedMarkerIndices.contains(index) ? 40 : 25;
          final MapLatLng markerLatLng = _markers.values.elementAt(index);
          Widget current = Icon(Icons.location_pin, size: size);
          return MapMarker(
            latitude: markerLatLng.latitude,
            longitude: markerLatLng.longitude,
            child: Transform.translate(
              offset: Offset(0.0, -size / 2),
              child: _selectedMarkerIndices.contains(index)
                  ? ScaleTransition(
                      alignment: Alignment.bottomCenter,
                      scale: _animation,
                      child: current)
                  : current,
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.animation),
        onPressed: () {
          _selectedMarkerIndices = [0, 2, 4];
          _tileLayerController.updateMarkers(_selectedMarkerIndices);
          _controller.repeat(min: 0.1, max: 1.0, reverse: true);
        },
      ),
    );
  }
}
```

![Animating Markers Dynamically in Futter Maps](https://www.syncfusion.com/blogs/wp-content/uploads/2021/05/Animating-Markers-Dynamically-in-Futter-Maps.gif)

Animating Markers Dynamically in Futter Maps

## **Animate a marker on interaction**

Assume we have a group of markers in which we are going to animate a single marker on a tap or click gesture.

For this, we need to wrap the marker’s child inside the [GestureDetector](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html)
 and use the [GestureDetector.onTap](https://api.flutter.dev/flutter/widgets/GestureDetector/onTap.html)
 callback to handle the tap interaction. On tapping, call [updateMarkers](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLayerController/updateMarkers.html)
 with the marker indices to animate it.

The following code demonstrates this.

```
int _selectedMarkerIndex = -1;
int _prevSelectedMarkerIndex = -1;

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Animate a single marker dynamically'),
    ),
    body: MapTileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      initialZoomLevel: 3,
      initialFocalLatLng: MapLatLng(2.3104, 16.5581),
      controller: _tileLayerController,
      initialMarkersCount: _markers.length,
      markerBuilder: (BuildContext context, int index) =>
          _buildMarker(context, index),
    ),
  );
}

MapMarker _buildMarker(BuildContext context, int index) {
  final double size = _selectedMarkerIndex == index ? 40 : 25;
  final MapLatLng markerLatLng = _markers.values.elementAt(index);
  final Icon current = Icon(Icons.location_pin);
  return MapMarker(
    latitude: markerLatLng.latitude,
    longitude: markerLatLng.longitude,
    child: GestureDetector(
      onTap: () {
        _prevSelectedMarkerIndex = _selectedMarkerIndex;
        _selectedMarkerIndex = index;
        _tileLayerController.updateMarkers([
          if (_prevSelectedMarkerIndex != -1) _prevSelectedMarkerIndex,
          _selectedMarkerIndex
        ]);
      },
      child: AnimatedContainer(
        transform: Matrix4.identity()..translate(0.0, -size / 2),
        duration: const Duration(milliseconds: 250),
        height: size,
        width: size,
        child: FittedBox(child: current),
      ),
    ),
  );
}
```

![Animate a Marker on Interaction in Flutter Maps](https://www.syncfusion.com/blogs/wp-content/uploads/2021/05/Animate-a-Marker-on-Interaction-in-Flutter-Maps.gif)

Animate a Marker on Interaction in Flutter Maps

## **Resource**

For more information, refer to this [animating markers on Flutter Maps project](https://github.com/SyncfusionExamples/flutter-maps-marker-animation)
 on GitHub.  
 [https://www.syncfusion.com/downloads/flutter](https://www.syncfusion.com/downloads/flutter)

## **Conclusion**

In this blog, we’ve learned how to animate a single marker and groups of markers at load time, dynamically, and also via interaction in the Syncfusion [Flutter Maps](https://www.syncfusion.com/flutter-widgets/flutter-maps)
 widget. Give it a try and leave your feedback in the comments section below.  
 Check out other features of our Flutter Maps in the [user guide](https://help.syncfusion.com/flutter/maps/)
 and explore our [Flutter Maps project samples](https://github.com/syncfusion/flutter-examples)
. Additionally, check out our demo apps available on different platforms: [Android](https://play.google.com/store/apps/details?id=com.syncfusion.flutter.examples)
, [iOS](https://apps.apple.com/us/app/syncfusion-flutter-ui-widgets/id1475231341)
, [web](https://flutter.syncfusion.com/?_ga=2.113248516.2088510317.1618203864-1079363253.1592211341)
, [Windows](https://www.microsoft.com/store/productId/9NHNBWCSF85D)
, and [Linux](https://snapcraft.io/syncfusion-flutter-gallery)
.  
 If you need a new widget for the Flutter framework or new features in our existing widgets, you can contact us through our [support forums](https://www.syncfusion.com/forums)
, [support portal](https://www.syncfusion.com/support/directtrac/incidents)
, or [feedback portal](https://www.syncfusion.com/feedback/flutter)
. As always, we are happy to assist you!

## Related Blogs

If you like this blog post, we think you will also like the following articles too:

- [How to Add Location Tracking to Your App Using Syncfusion Flutter Maps](https://www.syncfusion.com/blogs/post/how-to-add-location-tracking-to-your-app-using-syncfusion-flutter-maps.aspx)
- [How to Display Routes and Highlight Regions in Syncfusion Flutter Maps](https://www.syncfusion.com/blogs/post/how-to-display-routes-and-highlight-regions-in-syncfusion-flutter-maps.aspx)
- [How to Create a Choropleth Map in a Flutter Application](https://www.syncfusion.com/blogs/post/create-choropleth-map-using-in-flutter.aspx)
