summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/ios/src/MGLMapView.h19
-rw-r--r--platform/ios/src/MGLMapView.mm54
2 files changed, 42 insertions, 31 deletions
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index 63d799bda9..09142c4093 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -763,6 +763,25 @@ IB_DESIGNABLE
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
/**
+ Returns the point in this view's coordinate system on which to "anchor" in
+ response to a user-initiated gesture.
+
+ For example, a pinch-to-zoom gesture would anchor the map at the midpoint of
+ the pinch.
+
+ If the `userTrackingMode` property is not `MGLUserTrackingModeNone`, the
+ user annotation is used as the anchor point.
+
+ Subclasses may override this method to provide specialized behavior - for
+ example, anchoring on the map's center point to provide a "locked" zooming
+ mode.
+
+ @param gesture An anchorable user gesture.
+ @return The point on which to anchor in response to the gesture.
+ */
+- (CGPoint)anchorPointForGesture:(UIGestureRecognizer *)gesture;
+
+/**
The distance from the edges of the map view’s frame to the edges of the map
view’s logical viewport.
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 5d1bcb1109..4e304b23a5 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -1235,11 +1235,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
_mbglMap->cancelTransitions();
- CGPoint centerPoint = [pinch locationInView:pinch.view];
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- centerPoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint centerPoint = [self anchorPointForGesture:pinch];
if (pinch.state == UIGestureRecognizerStateBegan)
{
@@ -1311,7 +1307,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self unrotateIfNeededForGesture];
}
- _previousPinchCenterCoordinate = [self convertPoint:[pinch locationInView:pinch.view] toCoordinateFromView:self];
+ _previousPinchCenterCoordinate = [self convertPoint:centerPoint toCoordinateFromView:self];
_previousPinchNumberOfTouches = pinch.numberOfTouches;
}
@@ -1321,11 +1317,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
_mbglMap->cancelTransitions();
- CGPoint centerPoint = [rotate locationInView:rotate.view];
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- centerPoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint centerPoint = [self anchorPointForGesture:rotate];
if (rotate.state == UIGestureRecognizerStateBegan)
{
@@ -1454,11 +1446,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
if (doubleTap.state == UIGestureRecognizerStateEnded)
{
[self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
- CGPoint gesturePoint = [doubleTap locationInView:doubleTap.view];
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- gesturePoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint gesturePoint = [self anchorPointForGesture:doubleTap];
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
_mbglMap->scaleBy(2, center, MGLDurationInSeconds(MGLAnimationDuration));
@@ -1486,11 +1474,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
else if (twoFingerTap.state == UIGestureRecognizerStateEnded)
{
- CGPoint gesturePoint = [twoFingerTap locationInView:twoFingerTap.view];
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- gesturePoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint gesturePoint = [self anchorPointForGesture:twoFingerTap];
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
_mbglMap->scaleBy(0.5, center, MGLDurationInSeconds(MGLAnimationDuration));
@@ -1528,11 +1512,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
if (newZoom < _mbglMap->getMinZoom()) return;
- CGPoint centerPoint = self.contentCenter;
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- centerPoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint centerPoint = [self anchorPointForGesture:quickZoom];
+
_mbglMap->scaleBy(powf(2, newZoom) / _mbglMap->getScale(),
mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
@@ -1564,11 +1545,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
CGFloat pitchNew = currentPitch - (gestureDistance / slowdown);
- CGPoint centerPoint = self.contentCenter;
- if (self.userTrackingMode != MGLUserTrackingModeNone)
- {
- centerPoint = self.userLocationAnnotationViewCenter;
- }
+ CGPoint centerPoint = [self anchorPointForGesture:twoFingerDrag];
+
_mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
@@ -1578,7 +1556,21 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self notifyGestureDidEndWithDrift:NO];
[self unrotateIfNeededForGesture];
}
+}
+- (CGPoint)anchorPointForGesture:(UIGestureRecognizer *)gesture {
+ if (self.userTrackingMode != MGLUserTrackingModeNone)
+ {
+ return self.userLocationAnnotationViewCenter;
+ }
+
+ // Special case for two-finger drag and quickzoom
+ if ([gesture isKindOfClass:[UIPanGestureRecognizer class]] || [gesture isKindOfClass:[UILongPressGestureRecognizer class]])
+ {
+ return self.contentCenter;
+ }
+
+ return [gesture locationInView:gesture.view];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer