only update on minimum distance

This commit is contained in:
Freek van de Ven 2021-10-01 15:00:23 +02:00
parent b9a867eaca
commit 38ac7476a5
6 changed files with 215 additions and 68 deletions

View file

@ -13,10 +13,13 @@ class TrackTraceDemo extends StatefulWidget {
class _TrackTraceDemoState extends State<TrackTraceDemo> {
TrackTraceController? controller;
int step = 1;
int routeLength = 0;
late final Timer timer;
@override
void initState() {
Timer.periodic(const Duration(seconds: 5), (_) {
timer = Timer.periodic(const Duration(seconds: 2), (_) {
moveAlongRoute();
});
super.initState();
@ -48,6 +51,18 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
{'visibility': 'off'},
],
),
// GoogleMapThemeFeature(
// featureType: 'water',
// stylers: [
// {'color': '#00ff00'}
// ],
// ),
// GoogleMapThemeFeature(
// featureType: 'road',
// stylers: [
// {'color': '#000000'}
// ],
// )
],
),
startPosition: const Marker(
@ -61,18 +76,37 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
googleAPIKey: 'AIzaSyDaxZX8TeQeVf5tW-D6A66WLl20arbWV6c',
travelMode: TravelMode.walking,
mapType: MapType.normal,
routeUpdateInterval: 60,
routeUpdateInterval: Duration(seconds: 30),
timerPrecision: TimePrecision.everySecond,
zoomGesturesEnabled: true,
scrollGesturesEnabled: true,
line: const Polyline(
jointType: JointType.bevel,
polylineId: PolylineId('test route'),
color: Color(0xFFFF7884),
width: 3,
),
onArrived: () {
timer.cancel();
debugPrint('stopping simulation');
},
onTap: (value) {
debugPrint(value.toString());
},
onLongPress: (value) {
debugPrint(value.toString());
},
onCameraMove: (value) {
debugPrint(value.toString());
},
onMapCreated: (ctr) => {
controller = ctr,
ctr.addListener(() {
setState(() {});
setState(() {
if (ctr.route != null && ctr.route!.distance != routeLength) {
step = 1;
}
});
}),
},
),
@ -100,10 +134,12 @@ class _TrackTraceDemoState extends State<TrackTraceDemo> {
controller!.start = Marker(
markerId: const MarkerId('Start Locatie'),
position: LatLng(
controller!.route!.line[1].latitude,
controller!.route!.line[1].longitude,
controller!.route!.line[step].latitude,
controller!.route!.line[step].longitude,
),
);
step++;
routeLength = controller!.route!.distance;
}
}
}

View file

@ -134,7 +134,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.1"
version: "1.0.0"
html:
dependency: transitive
description:

View file

@ -12,7 +12,16 @@ import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:http/http.dart' as http;
export 'package:google_maps_flutter/google_maps_flutter.dart'
show MapType, Marker, MarkerId, Polyline, PolylineId, LatLng;
show
MapType,
Marker,
MarkerId,
BitmapDescriptor,
InfoWindow,
Polyline,
PolylineId,
JointType,
LatLng;
part 'src/controller.dart';
part 'src/directions_repository.dart';

View file

@ -31,6 +31,36 @@ class TrackTraceController extends ChangeNotifier {
notifyListeners();
}
void recenterCamera() {
mapController?.moveCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(
min(
_startPosition.position.latitude,
_destinationPosition.position.latitude,
),
min(
_startPosition.position.longitude,
_destinationPosition.position.longitude,
),
),
northeast: LatLng(
max(
_startPosition.position.latitude,
_destinationPosition.position.latitude,
),
max(
_startPosition.position.longitude,
_destinationPosition.position.longitude,
),
),
),
50,
),
);
}
@override
void dispose() {
mapController?.dispose();
@ -40,10 +70,13 @@ class TrackTraceController extends ChangeNotifier {
class TrackTraceRoute {
TrackTraceRoute(
int durationValue, int distanceValue, List<PointLatLng> lineValue,)
: duration = durationValue,
int durationValue,
int distanceValue,
List<PointLatLng> lineValue,
) : duration = durationValue,
distance = distanceValue,
line = lineValue;
/// route duration in seconds
int duration = 0;
@ -51,5 +84,5 @@ TrackTraceRoute(
int distance = 0;
/// route edge points
final List<PointLatLng> line;
List<PointLatLng> line;
}

View file

@ -1,6 +1,5 @@
part of google_track_trace;
// typedef void MapCreatedCallback(TrackTraceController controller);
enum TimePrecision { updateOnly, everySecond, everyMinute }
class GoogleTrackTraceMap extends StatefulWidget {
@ -11,15 +10,29 @@ class GoogleTrackTraceMap extends StatefulWidget {
required this.googleAPIKey,
required this.routeUpdateInterval,
Key? key,
this.markerUpdatePrecision = 50,
this.timerPrecision = TimePrecision.everyMinute,
this.travelMode = TravelMode.driving,
this.cameraTargetBounds,
this.compassEnabled = false,
this.rotateGesturesEnabled = false,
this.scrollGesturesEnabled = false,
this.zoomControlsEnabled = false,
this.zoomGesturesEnabled = false,
this.liteModeEnabled = false,
this.tiltGesturesEnabled = false,
this.myLocationEnabled = false,
this.myLocationButtonEnabled = false,
this.mapToolbarEnabled = false,
this.mapType = MapType.normal,
this.buildingsEnabled = false,
this.indoorViewEnabled = false,
this.trafficEnabled = false,
this.mapStylingTheme,
this.onTap,
this.onArrived,
this.onLongPress,
this.onCameraMove,
this.line,
}) : super(key: key);
@ -31,8 +44,10 @@ class GoogleTrackTraceMap extends StatefulWidget {
final TravelMode travelMode;
final int routeUpdateInterval;
final Duration routeUpdateInterval;
/// amount of meter the marker needs to move to update
final int markerUpdatePrecision;
final TimePrecision timerPrecision;
final Marker startPosition;
@ -41,13 +56,26 @@ class GoogleTrackTraceMap extends StatefulWidget {
final Polyline? line;
final bool compassEnabled;
final bool rotateGesturesEnabled;
final bool scrollGesturesEnabled;
final bool liteModeEnabled;
final bool tiltGesturesEnabled;
final bool myLocationEnabled;
final bool myLocationButtonEnabled;
final bool zoomControlsEnabled;
final bool zoomGesturesEnabled;
final bool mapToolbarEnabled;
final bool buildingsEnabled;
final bool indoorViewEnabled;
final bool trafficEnabled;
final CameraTargetBounds? cameraTargetBounds;
final MapType mapType;
final GoogleTrackTraceMapTheme? mapStylingTheme;
final ArgumentCallback<LatLng>? onTap;
final void Function()? onArrived;
final ArgumentCallback<LatLng>? onLongPress;
final CameraPositionCallback? onCameraMove;
final String googleAPIKey;
@override
@ -59,12 +87,17 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
DateTime lastRouteUpdate = DateTime.now();
late final Timer routeCalculateTimer;
late final Timer markerUpdateTimer;
@override
void initState() {
super.initState();
controller =
TrackTraceController(widget.startPosition, widget.destinationPosition);
controller.addListener(_onChange);
controller.addListener(
() => setState(() {}),
);
widget.onMapCreated(controller);
startRouteUpdateTimer();
startMarkerUpdateTimer();
@ -84,12 +117,23 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
controller.end.position,
),
onMapCreated: _onMapCreated,
onTap: widget.onTap,
onLongPress: widget.onLongPress,
onCameraMove: widget.onCameraMove,
compassEnabled: widget.compassEnabled,
rotateGesturesEnabled: widget.rotateGesturesEnabled,
scrollGesturesEnabled: widget.scrollGesturesEnabled,
zoomControlsEnabled: widget.zoomControlsEnabled,
zoomGesturesEnabled: widget.zoomGesturesEnabled,
liteModeEnabled: widget.liteModeEnabled,
tiltGesturesEnabled: widget.tiltGesturesEnabled,
myLocationEnabled: widget.myLocationEnabled,
myLocationButtonEnabled: widget.myLocationButtonEnabled,
mapToolbarEnabled: widget.mapToolbarEnabled,
mapType: widget.mapType,
buildingsEnabled: widget.buildingsEnabled,
indoorViewEnabled: widget.indoorViewEnabled,
trafficEnabled: widget.trafficEnabled,
markers: <Marker>{
controller.start,
controller.end,
@ -115,10 +159,6 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
);
}
void _onChange() {
setState(() {});
}
void _onMapCreated(GoogleMapController ctr) {
if (mounted) {
controller.mapController = ctr;
@ -130,6 +170,7 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
'[{"featureType": "poi","stylers": [{"visibility": "off"}]}]',
);
}
controller.recenterCamera();
}
}
@ -138,7 +179,6 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
(pointA.latitude + pointB.latitude) / 2,
(pointA.longitude + pointB.longitude) / 2,
);
return CameraPosition(
target: target,
zoom: 13.0,
@ -147,26 +187,10 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
);
}
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 timer) {
routeCalculateTimer =
Timer.periodic(widget.routeUpdateInterval, (Timer timer) {
calculateRoute();
});
}
@ -175,10 +199,14 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
if (widget.timerPrecision != TimePrecision.updateOnly) {
var updateInterval =
(widget.timerPrecision == TimePrecision.everyMinute) ? 60 : 1;
markerUpdateTimer =
Timer.periodic(Duration(seconds: updateInterval), (timer) {
if (controller.route != null) {
checkDestinationCloseBy();
controller.route = TrackTraceRoute(
controller.route!.duration - updateInterval,
(controller.route!.duration != 0)
? controller.route!.duration - updateInterval
: 0,
controller.route!.distance,
controller.route!.line,
);
@ -188,6 +216,7 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
}
void calculateRoute() {
if (controller.route == null || checkTargetMoved()) {
DirectionsRepository() // TODO(freek): refactor this away
.getDirections(
origin: controller.start.position,
@ -202,19 +231,59 @@ class _GoogleTrackTraceMapState extends State<GoogleTrackTraceMap> {
value.totalDistance,
value.polylinePoints,
),
if (controller.mapController != null)
{
controller.mapController!.moveCamera(
moveCameraToCenter(
controller.start.position,
controller.end.position,
),
),
},
checkDestinationCloseBy(),
controller.recenterCamera(),
setState(() {
lastRouteUpdate = DateTime.now();
})
}),
},
);
}
}
void checkDestinationCloseBy() {
if (calculatePointProximity(
controller.start.position,
controller.end.position,
) <
widget.markerUpdatePrecision) {
routeCalculateTimer.cancel();
markerUpdateTimer.cancel();
if (controller.route != null) {
controller.route!.line = <PointLatLng>[controller.route!.line[1]];
controller.route!.distance = 0;
controller.route!.duration = 0;
}
widget.onArrived?.call();
}
}
bool checkTargetMoved() {
return calculatePointProximity(
controller.start.position,
LatLng(
controller.route!.line[0].latitude,
controller.route!.line[0].longitude,
),
) >=
widget.markerUpdatePrecision;
}
double calculatePointProximity(LatLng pointA, LatLng pointB) {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 -
c(
(pointA.latitude - pointB.latitude) * p,
) /
2 +
c(controller.route!.line[0].latitude * p) *
c(pointA.latitude * p) *
(1 -
c(
(pointA.longitude - pointB.longitude) * p,
)) /
2;
return 12742 * asin(sqrt(a)) * 1000;
}
}

View file

@ -1,6 +1,6 @@
name: google_track_trace
description: An Iconica Flutter pluginin for Track & Trace Package
version: 0.0.1
version: 1.0.0
environment:
sdk: ">=2.14.0 <3.0.0"