animated_marker 0.3.3
animated_marker: ^0.3.3 copied to clipboard
Animate Google Maps markers smoothly between location updates.
animated_marker #
Smooth marker movement and rotation interpolation for Flutter Google Maps.
AnimatedMarker continuously interpolates position (LatLng), bearing/rotation (shortest angular path), alpha, and z-index between location updates without blocking the UI or causing marker jumps. It uses google_maps_flutter_platform_interface under the hood to ensure seamless compatibility with any version of google_maps_flutter without native plugin conflicts.
Features #
- Smooth Interpolation: Automatically animates position changes and spherical angle rotations between location updates.
- Static vs Animated Partitioning: Isolate non-moving markers via
staticMarkersso only active markers undergo ticker calculations. - Viewport Culling: Skip interpolation for markers outside the current viewport via
viewportBoundsor dynamicviewportBoundsListenable. - Adaptive Performance Tuning: Centralized
AnimationPolicywith frame-health monitoring (adaptiveEnabled,allowSnapOnLow, andAdaptiveProfiletiers) that automatically reduces frame rate under device load to preserve 60 FPS UI responsiveness. - Zero-Friction DX: Accepts standard
Set<Marker>and outputs the effectiveSet<Marker>directly into yourGoogleMapwidget builder.
Installation #
Add via CLI:
flutter pub add animated_marker
Or add to your pubspec.yaml:
dependencies:
animated_marker: ^<latest>
google_maps_flutter: ^<latest>
Quick Start #
import 'package:animated_marker/animated_marker.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class FleetTrackingMap extends StatelessWidget {
const FleetTrackingMap({
super.key,
required this.movingVehicles,
required this.staticDepots,
});
final Set<Marker> movingVehicles;
final Set<Marker> staticDepots;
@override
Widget build(BuildContext context) {
return AnimatedMarker(
animatedMarkers: movingVehicles,
staticMarkers: staticDepots,
animationPolicy: const AnimationPolicy(
duration: Duration(seconds: 2),
curve: Curves.easeInOut,
maxFps: 30,
adaptiveEnabled: true,
),
builder: (BuildContext context, Set<Marker> markers) {
return GoogleMap(
initialCameraPosition: const CameraPosition(
target: LatLng(37.77483, -122.41942),
zoom: 14,
),
markers: markers,
);
},
);
}
}
Advanced Policy Configuration #
Configure runtime animation behavior, viewport bounds, and adaptive quality via AnimationPolicy:
AnimationPolicy(
// Duration of marker transition between updates:
duration: const Duration(milliseconds: 1500),
// Motion curve:
curve: Curves.easeOutCubic,
// Target FPS ceiling for smooth movement:
maxFps: 30,
// Optional: static viewport bounds to skip interpolation for off-screen markers:
viewportBounds: currentVisibleBounds,
// Optional: dynamic bounds listenable to guard viewport without parent rebuilds:
viewportBoundsListenable: visibleBoundsNotifier,
// Adaptive quality mode: automatically down-samples FPS when frame drops occur:
adaptiveEnabled: true,
minFps: 15,
allowSnapOnLow: true,
adaptationCooldown: const Duration(seconds: 2),
)
How It Works #
- Shortest Angular Rotation: Angles are normalized and lerped along the shortest rotational path, preventing full 360° spin-arounds when crossing the 0°/360° meridian.
- State Transition Continuity: If a marker's target updates mid-flight, the animation picks up smoothly from its current rendered position rather than resetting or jumping to the original origin.
- Pure Platform Interface: Built against
google_maps_flutter_platform_interfacerather than native plugins, making it lightweight and compatible across Android, iOS, and Web.