summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-01-19 11:06:24 -0800
committerMinh Nguyễn <mxn@1ec5.org>2016-01-20 11:02:31 -0800
commit5a0042738673d5ed05d9ccc1916d7cd2b28f06f8 (patch)
tree7f021a163177fd2e2b0dc1793efd9ff65c5c621f
parent65f6eb25b5a0ef4e6feb712faceb71a44779f54f (diff)
downloadqtlocation-mapboxgl-5a0042738673d5ed05d9ccc1916d7cd2b28f06f8.tar.gz
[ios] Maintain user tracking, anchor on user dot during zoom, rotate
Per MapKit behavior, zooming or rotating with a gesture can no longer kick the user out of user tracking mode. In user tracking mode, the zoom animation is always anchored on the user dot, wherever it may be.
-rw-r--r--CHANGELOG.md2
-rw-r--r--platform/ios/src/MGLMapView.mm82
2 files changed, 40 insertions, 44 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 444e0a74f0..f473bbef0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -48,7 +48,7 @@ Known issues:
- MGLMapCamera’s `altitude` values now match those of MKMapCamera. ([#3362](https://github.com/mapbox/mapbox-gl-native/pull/3362))
- MGLMapView properties like `centerCoordinate` and `camera` now offset the center to account for any translucent top or bottom bar. As a result, when user tracking is enabled and the map view is an immediate child of a view controller, the user dot is centered in the unobscured portion of the map view. To override this offset, modify the `contentInset` property; you may also need to set the containing view controller’s `automaticallyAdjustsScrollViewInsets` property to `NO`. ([#3583](https://github.com/mapbox/mapbox-gl-native/pull/3583))
- In user tracking mode, the user dot stays in a fixed position within MGLMapView while the map pans smoothly. A new property, `userLocationVerticalAlignment`, determines the user dot’s fixed position. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589))
-- The user dot’s callout view is now centered above the user dot. It was previously offset slightly to the left. ([#3261](https://github.com/mapbox/mapbox-gl-native/pull/3261))
+- Zooming and rotation gestures no longer disable user tracking mode. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589))
- Fixed an issue with small map views not properly fitting annotations within bounds. (#[3407](https://github.com/mapbox/mapbox-gl-native/pull/3407))
- When the user rotates the map to within 7° of true north, the map view now snaps to true north. ([#3403](https://github.com/mapbox/mapbox-gl-native/pull/3403))
- The map view’s background can now be transparent or translucent, as long as the style’s background layer is transparent or translucent and `MGLMapView.opaque` is set to `NO`. ([#3096](https://github.com/mapbox/mapbox-gl-native/pull/3096))
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index d1639f4583..a728641ab8 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -849,6 +849,13 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
return UIEdgeInsetsInsetRect(self.bounds, self.contentInset);
}
+/// Returns the center point of the inset content within the map view.
+- (CGPoint)contentCenter
+{
+ CGRect contentFrame = self.contentFrame;
+ return CGPointMake(CGRectGetMidX(contentFrame), CGRectGetMidY(contentFrame));
+}
+
#pragma mark - Life Cycle -
- (void)updateFromDisplayLink
@@ -1094,14 +1101,18 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
if (_mbglMap->getZoom() <= _mbglMap->getMinZoom() && pinch.scale < 1) return;
_mbglMap->cancelTransitions();
+
+ CGPoint centerPoint = [pinch locationInView:pinch.view];
+ if (self.userTrackingMode != MGLUserTrackingModeNone)
+ {
+ centerPoint = self.userLocationAnnotationViewCenter;
+ }
if (pinch.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
self.scale = _mbglMap->getScale();
-
- self.userTrackingMode = MGLUserTrackingModeNone;
[self notifyGestureDidBegin];
}
@@ -1110,10 +1121,8 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
CGFloat newScale = self.scale * pinch.scale;
if (log2(newScale) < _mbglMap->getMinZoom()) return;
-
- mbgl::PrecisionPoint center([pinch locationInView:pinch.view].x,
- [pinch locationInView:pinch.view].y);
- _mbglMap->setScale(newScale, center);
+
+ _mbglMap->setScale(newScale, { centerPoint.x, centerPoint.y });
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
}
@@ -1149,9 +1158,7 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
if (velocity)
{
- CGPoint pinchCenter = [pinch locationInView:pinch.view];
- mbgl::PrecisionPoint center(pinchCenter.x, pinchCenter.y);
- _mbglMap->setScale(newScale, center, MGLDurationInSeconds(duration));
+ _mbglMap->setScale(newScale, { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration));
}
[self notifyGestureDidEndWithDrift:velocity];
@@ -1165,14 +1172,18 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
if ( ! self.isRotateEnabled) return;
_mbglMap->cancelTransitions();
+
+ CGPoint centerPoint = [rotate locationInView:rotate.view];
+ if (self.userTrackingMode != MGLUserTrackingModeNone)
+ {
+ centerPoint = self.userLocationAnnotationViewCenter;
+ }
if (rotate.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
self.angle = MGLRadiansFromDegrees(_mbglMap->getBearing()) * -1;
-
- self.userTrackingMode = MGLUserTrackingModeNone;
[self notifyGestureDidBegin];
}
@@ -1187,10 +1198,8 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
newDegrees = fminf(newDegrees, 30);
newDegrees = fmaxf(newDegrees, -30);
}
-
- mbgl::PrecisionPoint center([rotate locationInView:rotate.view].x,
- [rotate locationInView:rotate.view].y);
- _mbglMap->setBearing(newDegrees, center);
+
+ _mbglMap->setBearing(newDegrees, { centerPoint.x, centerPoint.y });
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
}
@@ -1205,7 +1214,7 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
CGFloat newRadians = radians + velocity * duration * 0.1;
CGFloat newDegrees = MGLDegreesFromRadians(newRadians) * -1;
- _mbglMap->setBearing(newDegrees, MGLDurationInSeconds(duration));
+ _mbglMap->setBearing(newDegrees, { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration));
[self notifyGestureDidEndWithDrift:YES];
@@ -1279,24 +1288,13 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
}
else if (doubleTap.state == UIGestureRecognizerStateEnded)
{
- CGPoint doubleTapPoint = [doubleTap locationInView:doubleTap.view];
-
- CGPoint zoomInPoint = doubleTapPoint;
- CGPoint userPoint = [self convertCoordinate:self.userLocation.coordinate toPointToView:self];
+ CGPoint gesturePoint = [doubleTap locationInView:doubleTap.view];
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
- CGRect userLocationRect = CGRectMake(userPoint.x - 40, userPoint.y - 40, 80, 80);
- if (CGRectContainsPoint(userLocationRect, doubleTapPoint))
- {
- zoomInPoint = userPoint;
- }
- }
- if ( ! CGPointEqualToPoint(zoomInPoint, userPoint))
- {
- self.userTrackingMode = MGLUserTrackingModeNone;
+ gesturePoint = self.userLocationAnnotationViewCenter;
}
- mbgl::PrecisionPoint center(zoomInPoint.x, zoomInPoint.y);
+ mbgl::PrecisionPoint center(gesturePoint.x, gesturePoint.y);
_mbglMap->scaleBy(2, center, MGLDurationInSeconds(MGLAnimationDuration));
__weak MGLMapView *weakSelf = self;
@@ -1322,20 +1320,13 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
}
else if (twoFingerTap.state == UIGestureRecognizerStateEnded)
{
- CGPoint zoomOutPoint;
-
+ CGPoint gesturePoint = [twoFingerTap locationInView:twoFingerTap.view];
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
- zoomOutPoint = self.center;
- }
- else
- {
- self.userTrackingMode = MGLUserTrackingModeNone;
-
- zoomOutPoint = CGPointMake([twoFingerTap locationInView:twoFingerTap.view].x, [twoFingerTap locationInView:twoFingerTap.view].y);
+ gesturePoint = self.userLocationAnnotationViewCenter;
}
- mbgl::PrecisionPoint center(zoomOutPoint.x, zoomOutPoint.y);
+ mbgl::PrecisionPoint center(gesturePoint.x, gesturePoint.y);
_mbglMap->scaleBy(0.5, center, MGLDurationInSeconds(MGLAnimationDuration));
__weak MGLMapView *weakSelf = self;
@@ -1370,9 +1361,14 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
CGFloat newZoom = log2f(self.scale) + (distance / 75);
if (newZoom < _mbglMap->getMinZoom()) return;
-
- mbgl::PrecisionPoint center(self.bounds.size.width / 2, self.bounds.size.height / 2);
- _mbglMap->scaleBy(powf(2, newZoom) / _mbglMap->getScale(), center);
+
+ CGPoint centerPoint = self.contentCenter;
+ if (self.userTrackingMode != MGLUserTrackingModeNone)
+ {
+ centerPoint = self.userLocationAnnotationViewCenter;
+ }
+ _mbglMap->scaleBy(powf(2, newZoom) / _mbglMap->getScale(),
+ { centerPoint.x, centerPoint.y });
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
}