Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios] Avoid jumping when setting user tracking mode
Browse files Browse the repository at this point in the history
Account for the user dot’s alignment when flying to the initial user location. Previously, during incremental location updates, we relied on a hack in which the edge insets resulted in a 0×0 viewport, forcing the center upward or downward. But flyTo() relies on the viewport’s size to control the trajectory. So instead, all location updates now use a correctly-sized viewport centered on the offset user dot.
  • Loading branch information
1ec5 committed Jan 25, 2016
1 parent ef6886e commit 7b820ab
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,7 @@ - (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration a
return;
}

mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera];
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:self.contentInset];
mbgl::AnimationOptions animationOptions;
if (duration > 0)
{
Expand Down Expand Up @@ -1984,18 +1984,18 @@ - (void)flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration
{
self.userTrackingMode = MGLUserTrackingModeNone;

[self _flyToCamera:camera withDuration:duration peakAltitude:peakAltitude completionHandler:completion];
[self _flyToCamera:camera edgePadding:self.contentInset withDuration:duration peakAltitude:peakAltitude completionHandler:completion];
}

- (void)_flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
- (void)_flyToCamera:(MGLMapCamera *)camera edgePadding:(UIEdgeInsets)insets withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();
if ([self.camera isEqual:camera])
{
return;
}

mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera];
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets];
mbgl::AnimationOptions animationOptions;
if (duration >= 0)
{
Expand Down Expand Up @@ -2024,14 +2024,14 @@ - (void)_flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duratio

/// Returns a CameraOptions object that specifies parameters for animating to
/// the given camera.
- (mbgl::CameraOptions)cameraOptionsObjectForAnimatingToCamera:(MGLMapCamera *)camera
- (mbgl::CameraOptions)cameraOptionsObjectForAnimatingToCamera:(MGLMapCamera *)camera edgePadding:(UIEdgeInsets)insets
{
mbgl::CameraOptions options;
if (CLLocationCoordinate2DIsValid(camera.centerCoordinate))
{
options.center = MGLLatLngFromLocationCoordinate2D(camera.centerCoordinate);
}
options.padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
options.padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
options.zoom = MGLZoomLevelForAltitude(camera.altitude, camera.pitch,
camera.centerCoordinate.latitude,
self.frame.size);
Expand Down Expand Up @@ -3051,7 +3051,6 @@ - (void)setUserTrackingMode:(MGLUserTrackingMode)mode animated:(BOOL)animated
if (self.zoomLevel < self.currentMinimumZoom)
{
[self setZoomLevel:self.currentMinimumZoom animated:YES];
_userTrackingMode = MGLUserTrackingModeFollowWithHeading; // reapply
}

if (self.userLocationAnnotationView)
Expand Down Expand Up @@ -3127,16 +3126,28 @@ - (void)locationManager:(__unused CLLocationManager *)manager didUpdateLocations

if (std::abs(currentPoint.x - correctPoint.x) > 1.0 || std::abs(currentPoint.y - correctPoint.y) > 1.0)
{
CLLocationDirection course = self.userLocation.location.course;
if (course < 0 || self.userTrackingMode != MGLUserTrackingModeFollowWithCourse)
{
course = -1;
}

// Shift the center point upward or downward to accommodate a
// shifted user location annotation view.
CGRect bounds = self.bounds;
CGRect boundsAroundCorrectPoint = CGRectOffset(bounds,
correctPoint.x - CGRectGetMidX(bounds),
correctPoint.y - CGRectGetMidY(bounds));
UIEdgeInsets insets = UIEdgeInsetsMake(CGRectGetMinY(boundsAroundCorrectPoint) - CGRectGetMinY(bounds), 0,
CGRectGetMaxY(bounds) - CGRectGetMaxY(boundsAroundCorrectPoint), 0);

if (self.zoomLevel >= MGLMinimumZoomLevelForUserTracking)
{
// at sufficient detail, just re-center the map; don't zoom
//
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);
CAMediaTimingFunction *linearFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[self _setCenterCoordinate:self.userLocation.location.coordinate
edgePadding:insets
Expand All @@ -3157,7 +3168,7 @@ - (void)locationManager:(__unused CLLocationManager *)manager didUpdateLocations
camera.heading = course;

__weak MGLMapView *weakSelf = self;
[self _flyToCamera:camera withDuration:animated ? -1 : 0 peakAltitude:-1 completionHandler:^{
[self _flyToCamera:camera edgePadding:insets withDuration:animated ? -1 : 0 peakAltitude:-1 completionHandler:^{
MGLMapView *strongSelf = weakSelf;
strongSelf.userTrackingState = MGLUserTrackingStateChanged;
}];
Expand All @@ -3177,7 +3188,7 @@ - (void)locationManager:(__unused CLLocationManager *)manager didUpdateLocations
self.frame.size);

__weak MGLMapView *weakSelf = self;
[self _flyToCamera:camera withDuration:animated ? -1 : 0 peakAltitude:-1 completionHandler:^{
[self _flyToCamera:camera edgePadding:insets withDuration:animated ? -1 : 0 peakAltitude:-1 completionHandler:^{
MGLMapView *strongSelf = weakSelf;
strongSelf.userTrackingState = MGLUserTrackingStateChanged;
}];
Expand Down

0 comments on commit 7b820ab

Please sign in to comment.