navigation_map.dart 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import 'dart:async';
  2. import 'dart:math';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_map/flutter_map.dart';
  5. import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
  6. import 'package:geolocator/geolocator.dart';
  7. import 'package:latlong2/latlong.dart';
  8. class NavigationMap extends StatefulWidget {
  9. final Stream<List<LatLng>> waypointsCoordinates;
  10. final Stream<int> currentWaypointIndexStream;
  11. const NavigationMap({
  12. required this.waypointsCoordinates,
  13. required this.currentWaypointIndexStream,
  14. Key? key,
  15. }) : super(key: key);
  16. @override
  17. State<NavigationMap> createState() => _NavigationMapState();
  18. }
  19. class _NavigationMapState extends State<NavigationMap> {
  20. /// Lines drawn on the map to indicate the path
  21. List<LatLng> _polylines = [];
  22. /// Used to differentiate the path before and after the user
  23. int _currentWaypointIndex = 0;
  24. final List<StreamSubscription<dynamic>> _streamsSubscription = [];
  25. late CenterOnLocationUpdate _centerOnLocationUpdate;
  26. late StreamController<double> _centerCurrentLocationStreamController;
  27. @override
  28. void initState() {
  29. super.initState();
  30. _centerOnLocationUpdate = CenterOnLocationUpdate.always;
  31. _centerCurrentLocationStreamController = StreamController<double>();
  32. _streamsSubscription.add(widget.waypointsCoordinates.listen(_updatePolylines));
  33. _streamsSubscription.add(widget.currentWaypointIndexStream.listen(_updateWaypointIndex));
  34. }
  35. void _updatePolylines(List<LatLng> waypointsCoordinates) {
  36. setState(() {
  37. _polylines = waypointsCoordinates.map((waypoint) => LatLng(waypoint.latitude, waypoint.longitude)).toList();
  38. });
  39. }
  40. void _updateWaypointIndex(int newWaypointIndex) {
  41. setState(() {
  42. _currentWaypointIndex = newWaypointIndex;
  43. });
  44. }
  45. @override
  46. Widget build(BuildContext context) {
  47. return SizedBox(
  48. height: MediaQuery.of(context).size.height * 0.8,
  49. child: FlutterMap(
  50. options: MapOptions(
  51. center: LatLng(0, 0),
  52. zoom: 15,
  53. minZoom: 10,
  54. maxZoom: 18,
  55. onPositionChanged: (MapPosition position, bool hasGesture) {
  56. if (hasGesture) {
  57. setState(() => _centerOnLocationUpdate = CenterOnLocationUpdate.never);
  58. }
  59. },
  60. ),
  61. children: [
  62. TileLayerWidget(
  63. options: TileLayerOptions(
  64. urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
  65. subdomains: ['a', 'b', 'c'],
  66. ),
  67. ),
  68. LocationMarkerLayerWidget(
  69. plugin: LocationMarkerPlugin(
  70. centerOnLocationUpdate: _centerOnLocationUpdate,
  71. centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
  72. ),
  73. options: LocationMarkerLayerOptions(
  74. marker: const DefaultLocationMarker(
  75. color: Colors.blue,
  76. ),
  77. positionStream: const LocationMarkerDataStreamFactory().geolocatorPositionStream(
  78. stream: Geolocator.getPositionStream(
  79. locationSettings: const LocationSettings(
  80. accuracy: LocationAccuracy.bestForNavigation,
  81. distanceFilter: 1,
  82. ),
  83. ),
  84. ),
  85. ),
  86. ),
  87. PolylineLayerWidget(
  88. options: PolylineLayerOptions(
  89. polylines: [
  90. Polyline(
  91. points: _polylines.sublist(max(0, _currentWaypointIndex - 1)),
  92. color: Colors.red,
  93. strokeWidth: 10,
  94. ),
  95. Polyline(
  96. points: _polylines.sublist(0, max(0, _currentWaypointIndex)),
  97. color: Colors.green,
  98. strokeWidth: 10,
  99. ),
  100. ],
  101. ),
  102. ),
  103. ],
  104. ),
  105. );
  106. }
  107. @override
  108. void dispose() {
  109. for (final streamSubscription in _streamsSubscription) {
  110. streamSubscription.cancel();
  111. }
  112. super.dispose();
  113. }
  114. }