mirror of
https://github.com/Iconica-Development/flutter_google_track_and_trace.git
synced 2025-05-19 13:13:44 +02:00
update demo to amsterdam travel
This commit is contained in:
parent
a39de81555
commit
ed11998739
4 changed files with 124 additions and 121 deletions
|
@ -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,44 +61,22 @@ 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) {
|
|
||||||
controller!.current = Marker(
|
|
||||||
markerId: MarkerId('Huidige 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) {
|
if (controller != null) {
|
||||||
controller!.start = Marker(
|
controller!.start = Marker(
|
||||||
markerId: MarkerId('Start Locatie'),
|
markerId: const 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,
|
position: LatLng(51.93 + Random().nextDouble() * 0.06,
|
||||||
6.23 + Random().nextDouble() * 0.08));
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +97,22 @@ 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(
|
||||||
|
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,
|
color: Theme.of(context).primaryColor,
|
||||||
width: 4,
|
width: 4,
|
||||||
points: route!.polylinePoints
|
points: controller.route!.line
|
||||||
.map((e) => LatLng(e.latitude, e.longitude))
|
.map((e) => LatLng(e.latitude, e.longitude))
|
||||||
.toList(),
|
.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +139,21 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
|
||||||
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() {
|
|
||||||
if (route != null) {
|
|
||||||
trackTraceController.duration = route!.totalDuration -
|
|
||||||
DateTime.now().difference(lastRouteUpdate).inSeconds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void calculateRoute() async {
|
void calculateRoute() async {
|
||||||
DirectionsRepository()
|
DirectionsRepository() //TODO refactor this away
|
||||||
.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;
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue