Animated Annotations
Smoothly animate annotation position changes using Flutter's animation system.
How it works
Annotation positions are updated via updateSymbol(). By driving updates from a Flutter AnimationController, you get smooth motion at the Flutter tick rate (typically 60fps).
Animate a symbol position
late AnimationController _animationController;
late Animation<double> _animation;
Symbol? _symbol;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
}
void _startAnimation(LatLng from, LatLng to) {
_animation.addListener(() {
final t = _animation.value;
final lat = from.latitude + (to.latitude - from.latitude) * t;
final lng = from.longitude + (to.longitude - from.longitude) * t;
controller.updateSymbol(
_symbol!,
SymbolOptions(geometry: LatLng(lat, lng)),
);
});
_animationController.forward(from: 0);
}
Or using lerpDouble from dart:ui:
_animationController.addListener(() {
final lat = lerpDouble(start.latitude, end.latitude, _animation.value)!;
final lng = lerpDouble(start.longitude, end.longitude, _animation.value)!;
controller.updateSymbol(
symbol,
SymbolOptions(geometry: LatLng(lat, lng)),
);
});
_animationController.forward();
Animate bearing (icon rotation)
_animationController.addListener(() {
final bearing = lerpDouble(startBearing, endBearing, _animation.value)!;
controller.updateSymbol(
symbol,
SymbolOptions(iconRotate: bearing),
);
});
This is useful for animated vehicle icons that rotate to face the direction of travel.
Continuous tracking animation
For real-time tracking (GPS updates), restart the animation on each new position:
void onNewPosition(LatLng newPos) {
final fromPos = _currentPos;
_currentPos = newPos;
_animationController.value = 0;
_from = fromPos;
_to = newPos;
_animationController.forward();
}
Performance
updateSymbol() triggers a style update on every frame. For very fast animations or many symbols simultaneously, consider switching to Style Layers with setGeoJsonFeature(), which batches updates more efficiently.