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

View file

@ -1,48 +1,56 @@
part of google_track_trace;
class TrackTraceController extends ChangeNotifier {
late final GoogleMapController _mapController;
Marker startPosition;
Marker destinationPosition;
Marker? currentPosition;
int durationInSeconds = 0;
GoogleMapController? _mapController;
Marker _startPosition;
Marker _destinationPosition;
TrackTraceRoute? _route;
TrackTraceController(Marker start, Marker destination)
: startPosition = start,
destinationPosition = destination;
: _startPosition = start,
_destinationPosition = destination;
set start(Marker start) {
startPosition = start;
notifyListeners();
}
set current(Marker? current) {
currentPosition = current;
_startPosition = start;
notifyListeners();
}
set end(Marker end) {
destinationPosition = end;
_destinationPosition = end;
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) {
durationInSeconds = duration;
set route(TrackTraceRoute? newRoute) {
_route = newRoute;
notifyListeners();
}
int get duration => durationInSeconds;
set mapController(GoogleMapController controller) {
set mapController(GoogleMapController? 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) {
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,
});
/// map the json response to a [Directions] object
factory Directions.fromMap(Map<String, dynamic> map) {
if ((map['routes'] as List).isEmpty) {
throw GoogleMapsException('No Routes available');
@ -92,7 +93,7 @@ class GoogleMapsException implements Exception {
@override
String toString() {
return 'Error occurred in Google Maps package:\n'
return 'Error occurred in Track&Trace package:\n'
'$message';
}
}

View file

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