summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-01-17 17:03:00 -0800
committerMinh Nguyễn <mxn@1ec5.org>2016-01-20 11:02:31 -0800
commit41ce7b2526ec338a10a1bfcfbee0a30342b2c49a (patch)
treea9f736d8c33d53620aa2770d94bb6f0f9a119d9f /platform
parent453000af3b17a8776ff0e78593dd5682c8cdab8d (diff)
downloadqtlocation-mapboxgl-41ce7b2526ec338a10a1bfcfbee0a30342b2c49a.tar.gz
[ios] Fly to user location
Fly to the user location when entering user tracking mode. Keep user location updates from interfering with the initial flight.
Diffstat (limited to 'platform')
-rw-r--r--platform/ios/src/MGLMapView.mm97
1 files changed, 54 insertions, 43 deletions
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 046ebfd433..89e1d34503 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -48,6 +48,16 @@
class MBGLView;
class MGLAnnotationContext;
+/// Indicates the manner in which the map view is tracking the user location.
+typedef NS_ENUM(NSUInteger, MGLUserTrackingState) {
+ /// The map view is not yet tracking the user location.
+ MGLUserTrackingStatePossible = 0,
+ /// The map view has begun to move to the first reported user location.
+ MGLUserTrackingStateBegan = 1,
+ /// The map view has finished moving to the first reported user location.
+ MGLUserTrackingStateChanged = 2,
+};
+
NSString *const MGLMapboxSetupDocumentationURLDisplayString = @"mapbox.com/help/first-steps-ios-sdk";
const NSTimeInterval MGLAnimationDuration = 0.3;
@@ -143,8 +153,8 @@ public:
/// Currently shown popover representing the selected annotation.
@property (nonatomic) UIView<MGLCalloutView> *calloutViewForSelectedAnnotation;
@property (nonatomic) MGLUserLocationAnnotationView *userLocationAnnotationView;
-/// True if the map view has completed its move to the first reported user location in user tracking mode.
-@property (nonatomic) BOOL hasBegunTrackingUserLocation;
+/// Indicates how thoroughly the map view is tracking the user location.
+@property (nonatomic) MGLUserTrackingState userTrackingState;
@property (nonatomic) CLLocationManager *locationManager;
@property (nonatomic) CGFloat scale;
@property (nonatomic) CGFloat angle;
@@ -1930,6 +1940,13 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
- (void)flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
{
+ self.userTrackingMode = MGLUserTrackingModeNone;
+
+ [self _flyToCamera:camera withDuration:duration peakAltitude:peakAltitude completionHandler:completion];
+}
+
+- (void)_flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
+{
_mbglMap->cancelTransitions();
if ([self.camera isEqual:camera])
{
@@ -2942,7 +2959,11 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
}
_userTrackingMode = mode;
- self.hasBegunTrackingUserLocation = NO;
+
+ if (_userTrackingMode == MGLUserTrackingModeNone
+ || _userTrackingMode == MGLUserTrackingModeFollowWithCourse) {
+ self.userTrackingState = MGLUserTrackingStatePossible;
+ }
switch (_userTrackingMode)
{
@@ -3038,8 +3059,9 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
{
// at sufficient detail, just re-center the map; don't zoom
//
- if (self.hasBegunTrackingUserLocation)
+ if (self.userTrackingState == MGLUserTrackingStateChanged)
{
+ // Ease incrementally to the new user location.
UIEdgeInsets insets = UIEdgeInsetsMake(correctPoint.y, correctPoint.x,
CGRectGetHeight(self.bounds) - correctPoint.y,
CGRectGetWidth(self.bounds) - correctPoint.x);
@@ -3052,51 +3074,39 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
animationTimingFunction:linearFunction
completionHandler:NULL];
}
- else
+ else if (self.userTrackingState == MGLUserTrackingStatePossible)
{
+ // Fly to the first reported location, which may be far away
+ // from the current viewport.
+ self.userTrackingState = MGLUserTrackingStateBegan;
+
+ MGLMapCamera *camera = self.camera;
+ camera.centerCoordinate = self.userLocation.location.coordinate;
+ camera.heading = course;
+
__weak MGLMapView *weakSelf = self;
- [self _setCenterCoordinate:self.userLocation.location.coordinate
- edgePadding:self.contentInset
- zoomLevel:self.zoomLevel
- direction:course
- duration:MGLAnimationDuration
- animationTimingFunction:nil
- completionHandler:^{
- MGLMapView *strongSelf = weakSelf;
- strongSelf.hasBegunTrackingUserLocation = YES;
- }];
+ [self _flyToCamera:camera withDuration:-1 peakAltitude:-1 completionHandler:^{
+ MGLMapView *strongSelf = weakSelf;
+ strongSelf.userTrackingState = MGLUserTrackingStateChanged;
+ }];
}
}
- else
+ else if (self.userTrackingState == MGLUserTrackingStatePossible)
{
// otherwise re-center and zoom in to near accuracy confidence
//
- float delta = (newLocation.horizontalAccuracy / 110000) * 1.2; // approx. meter per degree latitude, plus some margin
-
- CLLocationCoordinate2D desiredSouthWest = CLLocationCoordinate2DMake(newLocation.coordinate.latitude - delta,
- newLocation.coordinate.longitude - delta);
-
- CLLocationCoordinate2D desiredNorthEast = CLLocationCoordinate2DMake(newLocation.coordinate.latitude + delta,
- newLocation.coordinate.longitude + delta);
-
- CGFloat pixelRadius = fminf(self.bounds.size.width, self.bounds.size.height) / 2;
-
- CLLocationCoordinate2D actualSouthWest = [self convertPoint:CGPointMake(currentPoint.x - pixelRadius,
- currentPoint.y - pixelRadius)
- toCoordinateFromView:self];
-
- CLLocationCoordinate2D actualNorthEast = [self convertPoint:CGPointMake(currentPoint.x + pixelRadius,
- currentPoint.y + pixelRadius)
- toCoordinateFromView:self];
-
- if (desiredNorthEast.latitude != actualNorthEast.latitude ||
- desiredNorthEast.longitude != actualNorthEast.longitude ||
- desiredSouthWest.latitude != actualSouthWest.latitude ||
- desiredSouthWest.longitude != actualSouthWest.longitude)
- {
- // assumes we won't disrupt tracking mode
- [self setVisibleCoordinateBounds:MGLCoordinateBoundsMake(desiredSouthWest, desiredNorthEast) edgePadding:UIEdgeInsetsZero direction:course animated:YES];
- }
+ self.userTrackingState = MGLUserTrackingStateBegan;
+
+ MGLMapCamera *camera = self.camera;
+ camera.centerCoordinate = self.userLocation.location.coordinate;
+ camera.heading = course;
+ camera.altitude = newLocation.horizontalAccuracy;
+
+ __weak MGLMapView *weakSelf = self;
+ [self _flyToCamera:camera withDuration:-1 peakAltitude:-1 completionHandler:^{
+ MGLMapView *strongSelf = weakSelf;
+ strongSelf.userTrackingState = MGLUserTrackingStateChanged;
+ }];
}
[self unrotateIfNeededAnimated:YES];
}
@@ -3367,7 +3377,8 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
if ( ! self.userLocationAnnotationView.superview) [self.glView addSubview:self.userLocationAnnotationView];
CGPoint userPoint;
- if (self.userTrackingMode != MGLUserTrackingModeNone && self.hasBegunTrackingUserLocation)
+ if (self.userTrackingMode != MGLUserTrackingModeNone
+ && self.userTrackingState == MGLUserTrackingStateChanged)
{
userPoint = self.userLocationAnnotationViewCenter;
}