| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import 'dart:async';
- import 'dart:math';
- import 'package:flutter/material.dart';
- import 'package:flutter_map/flutter_map.dart';
- import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
- import 'package:geolocator/geolocator.dart';
- import 'package:latlong2/latlong.dart';
- class NavigationMap extends StatefulWidget {
- final Stream<List<LatLng>> waypointsCoordinates;
- final Stream<int> currentWaypointIndexStream;
- const NavigationMap({
- required this.waypointsCoordinates,
- required this.currentWaypointIndexStream,
- Key? key,
- }) : super(key: key);
- @override
- State<NavigationMap> createState() => _NavigationMapState();
- }
- class _NavigationMapState extends State<NavigationMap> {
- /// Lines drawn on the map to indicate the path
- List<LatLng> _polylines = [];
- /// Used to differentiate the path before and after the user
- int _currentWaypointIndex = 0;
- final List<StreamSubscription<dynamic>> _streamsSubscription = [];
- late CenterOnLocationUpdate _centerOnLocationUpdate;
- late StreamController<double> _centerCurrentLocationStreamController;
- @override
- void initState() {
- super.initState();
- _centerOnLocationUpdate = CenterOnLocationUpdate.always;
- _centerCurrentLocationStreamController = StreamController<double>();
- _streamsSubscription.add(widget.waypointsCoordinates.listen(_updatePolylines));
- _streamsSubscription.add(widget.currentWaypointIndexStream.listen(_updateWaypointIndex));
- }
- void _updatePolylines(List<LatLng> waypointsCoordinates) {
- setState(() {
- _polylines = waypointsCoordinates.map((waypoint) => LatLng(waypoint.latitude, waypoint.longitude)).toList();
- });
- }
- void _updateWaypointIndex(int newWaypointIndex) {
- setState(() {
- _currentWaypointIndex = newWaypointIndex;
- });
- }
- @override
- Widget build(BuildContext context) {
- return SizedBox(
- height: MediaQuery.of(context).size.height * 0.8,
- child: FlutterMap(
- options: MapOptions(
- center: LatLng(0, 0),
- zoom: 15,
- minZoom: 10,
- maxZoom: 18,
- onPositionChanged: (MapPosition position, bool hasGesture) {
- if (hasGesture) {
- setState(() => _centerOnLocationUpdate = CenterOnLocationUpdate.never);
- }
- },
- ),
- children: [
- TileLayerWidget(
- options: TileLayerOptions(
- urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
- subdomains: ['a', 'b', 'c'],
- ),
- ),
- LocationMarkerLayerWidget(
- plugin: LocationMarkerPlugin(
- centerOnLocationUpdate: _centerOnLocationUpdate,
- centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
- ),
- options: LocationMarkerLayerOptions(
- marker: const DefaultLocationMarker(
- color: Colors.blue,
- ),
- positionStream: const LocationMarkerDataStreamFactory().geolocatorPositionStream(
- stream: Geolocator.getPositionStream(
- locationSettings: const LocationSettings(
- accuracy: LocationAccuracy.bestForNavigation,
- distanceFilter: 1,
- ),
- ),
- ),
- ),
- ),
- PolylineLayerWidget(
- options: PolylineLayerOptions(
- polylines: [
- Polyline(
- points: _polylines.sublist(max(0, _currentWaypointIndex - 1)),
- color: Colors.red,
- strokeWidth: 10,
- ),
- Polyline(
- points: _polylines.sublist(0, max(0, _currentWaypointIndex)),
- color: Colors.green,
- strokeWidth: 10,
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- @override
- void dispose() {
- for (final streamSubscription in _streamsSubscription) {
- streamSubscription.cancel();
- }
- super.dispose();
- }
- }
|