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

[ios] Support for a customizable zoom gesture centering strategy. #5302

Merged
merged 2 commits into from
Jun 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions platform/ios/src/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,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.
Expand Down
54 changes: 23 additions & 31 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1235,11 +1235,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch

_mbglMap->cancelTransitions();

CGPoint centerPoint = [pinch locationInView:pinch.view];
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
centerPoint = self.userLocationAnnotationViewCenter;
}
CGPoint centerPoint = [self anchorPointForGesture:pinch];

if (pinch.state == UIGestureRecognizerStateBegan)
{
Expand Down Expand Up @@ -1311,7 +1307,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch
[self unrotateIfNeededForGesture];
}

_previousPinchCenterCoordinate = [self convertPoint:[pinch locationInView:pinch.view] toCoordinateFromView:self];
_previousPinchCenterCoordinate = [self convertPoint:centerPoint toCoordinateFromView:self];
_previousPinchNumberOfTouches = pinch.numberOfTouches;
}

Expand All @@ -1321,11 +1317,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate

_mbglMap->cancelTransitions();

CGPoint centerPoint = [rotate locationInView:rotate.view];
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
centerPoint = self.userLocationAnnotationViewCenter;
}
CGPoint centerPoint = [self anchorPointForGesture:rotate];

if (rotate.state == UIGestureRecognizerStateBegan)
{
Expand Down Expand Up @@ -1454,11 +1446,7 @@ - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap
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));
Expand Down Expand Up @@ -1486,11 +1474,7 @@ - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap
}
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));
Expand Down Expand Up @@ -1528,11 +1512,8 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom

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 });

Expand Down Expand Up @@ -1564,11 +1545,8 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag

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];
Expand All @@ -1578,7 +1556,21 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag
[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
Expand Down