update demo to amsterdam travel

This commit is contained in:
Freek van de Ven 2021-09-29 12:18:53 +02:00
parent a39de81555
commit ed11998739
4 changed files with 124 additions and 121 deletions

View file

@ -17,15 +17,8 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
@override @override
void initState() { void initState() {
// TODO: implement initState
Timer.periodic(const Duration(seconds: 10), (_) { Timer.periodic(const Duration(seconds: 10), (_) {
print('updating marker'); moveAlongRoute();
getRandomPointOnMap();
});
Timer.periodic(const Duration(seconds: 60), (_) {
print('updating route');
getRandomRoute();
}); });
super.initState(); super.initState();
} }
@ -34,24 +27,30 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: (controller == null) title: (controller == null || controller!.route == null)
? const Text('TrackTrace example') ? const Text('TrackTrace example')
: Text(controller!.duration.toString() + ' seconds')), : Text(controller!.route!.duration.toString() +
' seconds, afstand: ' +
(controller!.route!.distance / 1000).toString() +
' km')),
body: GoogleTrackTraceMap( body: GoogleTrackTraceMap(
startPosition: const Marker( startPosition: const Marker(
markerId: MarkerId('Start locatie'), markerId: MarkerId('Start locatie'),
position: LatLng(51.965578, 6.293439), position: LatLng(52.356057, 4.897540),
), ),
destinationPosition: const Marker( destinationPosition: const Marker(
markerId: MarkerId('Eind locatie'), markerId: MarkerId('Bestemming Locatie'),
position: LatLng(51.958996, 6.296520), position: LatLng(52.364709, 4.877157)),
),
googleAPIKey: 'AIzaSyDaxZX8TeQeVf5tW-D6A66WLl20arbWV6c', googleAPIKey: 'AIzaSyDaxZX8TeQeVf5tW-D6A66WLl20arbWV6c',
travelMode: TravelMode.walking, travelMode: TravelMode.bicycling,
routeUpdateInterval: 60, routeUpdateInterval: 60,
routeLabel: 'Test route',
timerPrecision: TimePrecision.everySecond, timerPrecision: TimePrecision.everySecond,
zoomGesturesEnabled: true, zoomGesturesEnabled: true,
line: const Polyline(
polylineId: PolylineId('test route'),
color: Colors.purple,
width: 7,
),
onMapCreated: (ctr) => { onMapCreated: (ctr) => {
controller = ctr, controller = ctr,
ctr.addListener(() { ctr.addListener(() {
@ -62,42 +61,20 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
); );
} }
void updateMap() {
controller!.current = const Marker(
markerId: MarkerId('Huidige locatie'),
position: LatLng(51.962578, 6.294439),
);
}
void getRandomPointOnMap() { void getRandomPointOnMap() {
// 51.989909, 6.234950 // 51.989909, 6.234950 NW
// 51.939909, 6.314950 SE
// 51.939909, 6.314950
if (controller != null) { if (controller != null) {
controller!.current = Marker( controller!.start = Marker(
markerId: MarkerId('Huidige Locatie'), markerId: const MarkerId('Start Locatie'),
position: LatLng(51.93 + Random().nextDouble() * 0.06, position: LatLng(51.93 + Random().nextDouble() * 0.06,
6.23 + Random().nextDouble() * 0.08)); 6.23 + Random().nextDouble() * 0.08));
} }
} }
void getRandomRoute() { void moveAlongRoute() {
// if (route != null) { if (controller != null && controller!.route != null && controller!.route!.line.length > 1) {
// print('removing point'); controller!.start = Marker(markerId: const MarkerId('Start Locatie'), position: LatLng(controller!.route!.line[1].latitude, controller!.route!.line[1].longitude));
// PointLatLng point = route!.polylinePoints[1];
// trackTraceController.startMarker = Marker(
// markerId: MarkerId('Start locatie'),
// position: LatLng(point.latitude, point.longitude));
// }
if (controller != null) {
controller!.start = Marker(
markerId: MarkerId('Start Locatie'),
position: LatLng(51.93 + Random().nextDouble() * 0.06,
6.23 + Random().nextDouble() * 0.08));
controller!.end = Marker(
markerId: MarkerId('Bestemming Locatie'),
position: LatLng(51.93 + Random().nextDouble() * 0.06,
6.23 + Random().nextDouble() * 0.08));
} }
} }
} }

View file

@ -1,48 +1,56 @@
part of google_track_trace; part of google_track_trace;
class TrackTraceController extends ChangeNotifier { class TrackTraceController extends ChangeNotifier {
late final GoogleMapController _mapController; GoogleMapController? _mapController;
Marker startPosition; Marker _startPosition;
Marker destinationPosition; Marker _destinationPosition;
Marker? currentPosition; TrackTraceRoute? _route;
int durationInSeconds = 0;
TrackTraceController(Marker start, Marker destination) TrackTraceController(Marker start, Marker destination)
: startPosition = start, : _startPosition = start,
destinationPosition = destination; _destinationPosition = destination;
set start(Marker start) { set start(Marker start) {
startPosition = start; _startPosition = start;
notifyListeners();
}
set current(Marker? current) {
currentPosition = current;
notifyListeners(); notifyListeners();
} }
set end(Marker end) { set end(Marker end) {
destinationPosition = end; _destinationPosition = end;
notifyListeners(); notifyListeners();
} }
Marker get start => startPosition; Marker get start => _startPosition;
Marker? get current => currentPosition; Marker get end => _destinationPosition;
Marker get end => destinationPosition; TrackTraceRoute? get route => _route;
set duration(int duration) { set route(TrackTraceRoute? newRoute) {
durationInSeconds = duration; _route = newRoute;
notifyListeners(); notifyListeners();
} }
int get duration => durationInSeconds; set mapController(GoogleMapController? controller) {
set mapController(GoogleMapController controller) {
_mapController = controller; _mapController = controller;
} }
GoogleMapController get mapController => _mapController; GoogleMapController? get mapController => _mapController;
}
class TrackTraceRoute {
/// route duration in seconds
int duration = 0;
/// route distance in meters
int distance = 0;
/// route edge points
List<PointLatLng> line;
TrackTraceRoute(
int durationValue, int distanceValue, List<PointLatLng> lineValue)
: duration = durationValue,
distance = distanceValue,
line = lineValue;
} }

View file

@ -35,7 +35,7 @@ class DirectionsRepository {
} on HttpException catch (e) { } on HttpException catch (e) {
print(e.message); print(e.message);
} }
throw GoogleMapsException('Unable to retrieve directions'); throw GoogleMapsException('Unable to retrieve directions from Google Maps API');
} }
} }
@ -52,6 +52,7 @@ class Directions {
required this.totalDuration, required this.totalDuration,
}); });
/// map the json response to a [Directions] object
factory Directions.fromMap(Map<String, dynamic> map) { factory Directions.fromMap(Map<String, dynamic> map) {
if ((map['routes'] as List).isEmpty) { if ((map['routes'] as List).isEmpty) {
throw GoogleMapsException('No Routes available'); throw GoogleMapsException('No Routes available');
@ -92,7 +93,7 @@ class GoogleMapsException implements Exception {
@override @override
String toString() { String toString() {
return 'Error occurred in Google Maps package:\n' return 'Error occurred in Track&Trace package:\n'
'$message'; '$message';
} }
} }

View file

@ -13,13 +13,15 @@ class GoogleTrackTraceMap extends StatefulWidget {
required this.routeUpdateInterval, required this.routeUpdateInterval,
this.timerPrecision = TimePrecision.everyMinute, this.timerPrecision = TimePrecision.everyMinute,
this.travelMode = TravelMode.driving, this.travelMode = TravelMode.driving,
this.routeLabel = '',
this.compassEnabled = false, this.compassEnabled = false,
this.zoomControlsEnabled = false, this.zoomControlsEnabled = false,
this.zoomGesturesEnabled = false, this.zoomGesturesEnabled = false,
this.mapToolbarEnabled = false, this.mapToolbarEnabled = false,
this.mapType = MapType.normal, this.mapType = MapType.normal,
this.buildingsEnabled = false, this.buildingsEnabled = false,
this.mapMarkations =
'[{"featureType": "poi","stylers": [{"visibility": "off"}]}]',
this.line,
}) : assert(true), }) : assert(true),
super(key: key); super(key: key);
@ -31,8 +33,6 @@ class GoogleTrackTraceMap extends StatefulWidget {
final TravelMode travelMode; final TravelMode travelMode;
final String routeLabel;
final int routeUpdateInterval; final int routeUpdateInterval;
final TimePrecision timerPrecision; final TimePrecision timerPrecision;
@ -40,6 +40,8 @@ class GoogleTrackTraceMap extends StatefulWidget {
final Marker startPosition; final Marker startPosition;
final Marker destinationPosition; final Marker destinationPosition;
Polyline? line;
final bool compassEnabled; final bool compassEnabled;
final bool zoomControlsEnabled; final bool zoomControlsEnabled;
final bool zoomGesturesEnabled; final bool zoomGesturesEnabled;
@ -47,6 +49,8 @@ class GoogleTrackTraceMap extends StatefulWidget {
final bool buildingsEnabled; final bool buildingsEnabled;
final MapType mapType; final MapType mapType;
final String mapMarkations;
CameraPosition initialCameraPosition = const CameraPosition( CameraPosition initialCameraPosition = const CameraPosition(
// doetinchem default initialCamera // doetinchem default initialCamera
target: LatLng(51.965578, 6.293439), target: LatLng(51.965578, 6.293439),
@ -59,25 +63,24 @@ class GoogleTrackTraceMap extends StatefulWidget {
} }
class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> { class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
late final TrackTraceController trackTraceController; late final TrackTraceController controller;
Directions? route;
DateTime lastRouteUpdate = DateTime.now(); DateTime lastRouteUpdate = DateTime.now();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
trackTraceController = controller =
TrackTraceController(widget.startPosition, widget.destinationPosition); TrackTraceController(widget.startPosition, widget.destinationPosition);
trackTraceController.addListener(_onChange); controller.addListener(_onChange);
widget.onMapCreated(trackTraceController); widget.onMapCreated(controller);
startRouteUpdateTimer(); startRouteUpdateTimer();
startMarkerUpdateTimer(); startMarkerUpdateTimer();
} }
@override @override
void dispose() { void dispose() {
trackTraceController.dispose(); controller.dispose();
super.dispose(); super.dispose();
} }
@ -85,8 +88,7 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GoogleMap( return GoogleMap(
initialCameraPosition: calculateCameraPosition( initialCameraPosition: calculateCameraPosition(
trackTraceController.start.position, controller.start.position, controller.end.position),
trackTraceController.end.position),
onMapCreated: _onMapCreated, onMapCreated: _onMapCreated,
compassEnabled: widget.compassEnabled, compassEnabled: widget.compassEnabled,
zoomControlsEnabled: widget.zoomControlsEnabled, zoomControlsEnabled: widget.zoomControlsEnabled,
@ -95,22 +97,25 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
mapType: widget.mapType, mapType: widget.mapType,
buildingsEnabled: widget.buildingsEnabled, buildingsEnabled: widget.buildingsEnabled,
markers: { markers: {
// style the markers controller.start,
trackTraceController.start, controller.end,
trackTraceController.end,
if (trackTraceController.current != null)
trackTraceController.current!,
}, },
polylines: { polylines: {
if (route != null) if (controller.route != null)
Polyline( (widget.line != null)
polylineId: PolylineId(widget.routeLabel), ? widget.line!.copyWith(
color: Theme.of(context).primaryColor, pointsParam: controller.route!.line
width: 4, .map((e) => LatLng(e.latitude, e.longitude))
points: route!.polylinePoints .toList())
.map((e) => LatLng(e.latitude, e.longitude)) : Polyline(
.toList(), // default PolyLine if none is provided
), polylineId: const PolylineId('track&trace route'),
color: Theme.of(context).primaryColor,
width: 4,
points: controller.route!.line
.map((e) => LatLng(e.latitude, e.longitude))
.toList(),
),
}); });
} }
@ -118,11 +123,10 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
setState(() {}); setState(() {});
} }
void _onMapCreated(GoogleMapController controller) { void _onMapCreated(GoogleMapController ctr) {
if (mounted) { if (mounted) {
trackTraceController.mapController = controller; controller.mapController = ctr;
controller.setMapStyle( ctr.setMapStyle(widget.mapMarkations); // move to dart json file
'[{"featureType": "poi","stylers": [{"visibility": "off"}]}]'); // move to dart json file
} }
} }
@ -130,11 +134,26 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
LatLng target = LatLng((pointA.latitude + pointB.latitude) / 2, LatLng target = LatLng((pointA.latitude + pointB.latitude) / 2,
(pointA.longitude + pointB.longitude) / 2); (pointA.longitude + pointB.longitude) / 2);
double calculatedZoom = 13.0; // TODO calculate this zoom double calculatedZoom = 13.0; // TODO calculate this zoom
return CameraPosition( return CameraPosition(
target: target, zoom: calculatedZoom, tilt: 0.0, bearing: 0.0); target: target, zoom: calculatedZoom, tilt: 0.0, bearing: 0.0);
} }
CameraUpdate moveCameraToCenter(LatLng pointA, LatLng pointB) {
return CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(
min(pointA.latitude, pointB.latitude),
min(pointA.longitude, pointB.longitude),
),
northeast: LatLng(
max(pointA.latitude, pointB.latitude),
max(pointA.longitude, pointB.longitude),
),
),
50);
}
void startRouteUpdateTimer() { void startRouteUpdateTimer() {
calculateRoute(); // run at the start calculateRoute(); // run at the start
Timer.periodic(Duration(seconds: widget.routeUpdateInterval), (timer) { Timer.periodic(Duration(seconds: widget.routeUpdateInterval), (timer) {
@ -144,37 +163,35 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
void startMarkerUpdateTimer() { void startMarkerUpdateTimer() {
if (widget.timerPrecision != TimePrecision.updateOnly) { if (widget.timerPrecision != TimePrecision.updateOnly) {
Timer.periodic( int updateInterval =
Duration( (widget.timerPrecision == TimePrecision.everyMinute) ? 60 : 1;
seconds: (widget.timerPrecision == TimePrecision.everyMinute) Timer.periodic(Duration(seconds: updateInterval), (timer) {
? 60 if (controller.route != null) {
: 1), (timer) { controller.route!.duration =
updateDurationTimer(); controller.route!.duration - updateInterval;
}
}); });
} }
} }
void updateDurationTimer() { void calculateRoute() async {
if (route != null) { DirectionsRepository() //TODO refactor this away
trackTraceController.duration = route!.totalDuration -
DateTime.now().difference(lastRouteUpdate).inSeconds;
}
}
void calculateRoute() async {
DirectionsRepository()
.getDirections( .getDirections(
origin: trackTraceController.start.position, origin: controller.start.position,
destination: trackTraceController.end.position, destination: controller.end.position,
mode: widget.travelMode, mode: widget.travelMode,
key: widget.googleAPIKey, key: widget.googleAPIKey,
) )
.then((value) => { .then((value) => {
trackTraceController.duration = value.totalDuration, controller.route = TrackTraceRoute(value.totalDuration,
trackTraceController.mapController.moveCamera(CameraUpdate.newCameraPosition(calculateCameraPosition(trackTraceController.start.position, trackTraceController.end.position))), value.totalDistance, value.polylinePoints),
if (controller.mapController != null)
{
controller.mapController!.moveCamera(moveCameraToCenter(
controller.start.position, controller.end.position)),
},
setState(() { setState(() {
lastRouteUpdate = DateTime.now(); lastRouteUpdate = DateTime.now();
route = value;
}) })
}); });
} }