summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Allen <mark.a.allen@gmail.com>2016-06-09 20:05:15 -0400
committerMinh Nguyễn <mxn@1ec5.org>2016-06-09 17:05:50 -0700
commitdd565b701b20cac69f7a84a02e7bc8a783c92bb6 (patch)
treeb5ed346e30aac9f75e5622b2ea901d7f6b550c5f
parent4e808994cb7611090c234875cffc18f0f3ef8088 (diff)
downloadqtlocation-mapboxgl-dd565b701b20cac69f7a84a02e7bc8a783c92bb6.tar.gz
[ios] Support for a customizable zoom gesture centering strategy. (#5302)
* [ios] Support for a customizable zoom gesture centering strategy. We introduce a new MGLZoomGestureCentering enum and corresponding zoomGestureCentering property on MGLMapView. Currently, Mapbox automatically adjusts the center of the map relative to the user's gesture location, but for some applications (e.g Uber, Lyft) it is preferable to keep the map center "locked" in response to zoom gestures. Exisiting code will retain its current behavior without modification and will implicitly use the default value of MGLZoomGestureCenteringFollowsTouch. New code can specify MGLZoomGestureCenteringLockedInPlace to get the new "locked" behavior. * [ios] Added -anchorPointForGesture: to MGLMapView Cherry-picked from b915f05a069d4658cc11d91a4bae2ef52c5fcbf1.
-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 f5720af665..6549ca16ec 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