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

Delegate method to restrict movement #5584

Merged
merged 14 commits into from
Feb 9, 2017

Conversation

1ec5
Copy link
Contributor

@1ec5 1ec5 commented Jul 5, 2016

Added a way for the delegate to restrict where the user can move within the map using gestures. This approach allows the developer to restrict to a non-rectangular region or vary the region by zoom level or pitch as necessary, such as to prevent the user from seeing beyond a certain region regardless of the degree of tilt.

This PR intentionally keeps things simple to unblock some key use cases. Future improvements could include implementing a “rubber band” effect, allowing the delegate to “redirect” the camera to some other camera (#2457 (comment)), and automatically restricting the camera to downloaded regions (#5042).

Before we can land this feature:

Fixes #2457.

/cc @boundsj @frederoni @friedbunny

@1ec5 1ec5 added feature iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS offline labels Jul 5, 2016
@1ec5 1ec5 added this to the ios-v3.4.0 milestone Jul 5, 2016
@1ec5 1ec5 self-assigned this Jul 5, 2016
@1ec5
Copy link
Contributor Author

1ec5 commented Jul 5, 2016

I think it’s too late for this feature to make the impending v3.3.0 final release, but we could easily backport it to v3.3.1 if it takes awhile to release v3.4.0.

@1ec5
Copy link
Contributor Author

1ec5 commented Jul 6, 2016

Note that this API does not affect programmatic movement of the viewport, such as via -flyToCamera:…, so we won’t run into mapbox/mapbox-gl-js#2521. If the developer wants to move to a viewport that the user wouldn’t be able to move to on their own, that’s the developer’s prerogative.

@1ec5 1ec5 modified the milestones: ios-v3.3.1, ios-v3.4.0 Jul 6, 2016
This method is called as soon as the user gesture is recognized. It is not
called in response to a programmatic camera change, such as by setting the
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add the standard, “this method is called many times during gesticulation so you should keep it as lightweight as possible”?

@friedbunny
Copy link
Contributor

friedbunny commented Jul 6, 2016

This only seems to prevent simple pans, so far. With the new delegate method set to always return NO, it’s still possible to move the map via flick, pinch + pan, and rotate + pan. Quick zoom also works.

@1ec5
Copy link
Contributor Author

1ec5 commented Jul 6, 2016

With the new delegate method set to always return NO, it’s still possible to move the map via flick, pinch + pan, and rotate + pan. Quick zoom also works.

Oh, you’re right! I took care of all the gesture recognizers for macOS but forgot to follow up for iOS.

@1ec5
Copy link
Contributor Author

1ec5 commented Jul 6, 2016

Another caveat about this approach is that, if the delegate decides to block the camera change, the camera actually does change (even sending the -mapView:didChangeRegionAnimated: message to the delegate) before the map view resets the camera.

@Zakay
Copy link

Zakay commented Jul 7, 2016

👍

@1ec5 1ec5 force-pushed the 1ec5-should-change-camera-2457 branch from 3366aa8 to 11253ec Compare July 10, 2016 22:24
@1ec5 1ec5 added the GL JS parity For feature parity with Mapbox GL JS label Jul 10, 2016
@1ec5 1ec5 added the ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold label Jul 11, 2016
@1ec5 1ec5 force-pushed the 1ec5-should-change-camera-2457 branch from 11253ec to ce3d847 Compare July 19, 2016 05:39
@1ec5 1ec5 modified the milestones: ios-v3.3.1, ios-v3.4.0 Jul 19, 2016
@1ec5 1ec5 added MapKit parity For feature parity with MapKit on iOS or macOS and removed MapKit parity For feature parity with MapKit on iOS or macOS labels Aug 15, 2016
@1ec5 1ec5 mentioned this pull request Sep 6, 2016
@maciekish
Copy link
Contributor

Any chance to see this in v3.3.1 please?

return camera;
}

- (double)currentCameraZoom
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is unnecessary; use self.zoomLevel instead.

return camera;
}

- (MGLMapCamera *)currentCameraWithEstimatedDegrees:(CGFloat)degrees anchorPoint:(CGPoint)anchorPoint
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CLLocationDirection to represent the map’s rotation in degrees.

Copy link
Contributor Author

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for hanging in there – just a few nits related to coding style.

// Calculates the final camera zoom, has no effect within current map camera.
MGLMapCamera *toCamera;
double zoom = log2(newScale);
toCamera = [self cameraByZoomingToZoomLevel:zoom aroundAnchorPoint:centerPoint];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare and set toCamera on the same line.

_mbglMap->moveBy({ delta.x, delta.y });
[pan setTranslation:CGPointZero inView:pan.view];

toCamera = [self cameraByPanningWithTranslation:delta panGesture:pan];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the declaration of toCamera down to this line.


// Calculates the final camera zoom, has no effect within current map camera.
MGLMapCamera *toCamera;
double zoom = log2(newScale);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: declare this a few lines further up to avoid saying log2(newScale) twice.


[self animateWithDelay:MGLAnimationDuration animations:^

MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: s/newZoom/self.zoomLevel + 1/

@fabian-guerra fabian-guerra force-pushed the 1ec5-should-change-camera-2457 branch 2 times, most recently from e6cec13 to a3e7277 Compare February 9, 2017 16:30
Copy link
Contributor Author

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nit left, but otherwise this is good to go.

MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:delta panGesture:pan];

if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
Copy link
Contributor Author

@1ec5 1ec5 Feb 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant: !A || (A && C) is equivalent to !A || C.

@1ec5 1ec5 dismissed incanus’s stale review February 9, 2017 19:04

My comments in #5584 (review) have been addressed; we’re OK with reporting metrics for aborted gestures; and @incanus’ nits have been addressed as well.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature GL JS parity For feature parity with Mapbox GL JS iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS offline
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants