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

Commit ce3d847

Browse files
committed
[ios, macos] Added delegate method to restrict movement
Added a way for the delegate to restrict where the user can move within the map using gestures. Fixes #2457.
1 parent 1bc4f0e commit ce3d847

File tree

6 files changed

+82
-0
lines changed

6 files changed

+82
-0
lines changed

platform/ios/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CON
55
## master
66

77
* Fixed an issue causing overlapping polylines and polygons to be drawn in undefined z-order. Shapes are always drawn in the order they are added to the map, from the oldest on the bottom to the newest on the top. ([#5710](https://github.com/mapbox/mapbox-gl-native/pull/5710))
8+
* Added a method to MGLMapViewDelegate, `-mapView:shouldChangeFromCamera:toCamera:`, that you can implement to restrict which parts the user can navigate to using gestures. ([#5584](https://github.com/mapbox/mapbox-gl-native/pull/5584))
89
* As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143))
910
* Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628))
1011
* Fixed an issue causing polyline and polygon annotations to disappear when the zoom level is one less than the maximum zoom level. ([#5418](https://github.com/mapbox/mapbox-gl-native/pull/5418))

platform/ios/src/MGLMapView.mm

+10
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,8 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
11891189

11901190
_mbglMap->cancelTransitions();
11911191

1192+
MGLMapCamera *oldCamera = self.camera;
1193+
BOOL didChangeCamera = NO;
11921194
if (pan.state == UIGestureRecognizerStateBegan)
11931195
{
11941196
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
@@ -1202,6 +1204,7 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
12021204
CGPoint delta = [pan translationInView:pan.view];
12031205
_mbglMap->moveBy({ delta.x, delta.y });
12041206
[pan setTranslation:CGPointZero inView:pan.view];
1207+
didChangeCamera = YES;
12051208

12061209
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
12071210
}
@@ -1234,6 +1237,13 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
12341237
MGLEventKeyZoomLevel: @(zoom)
12351238
}];
12361239
}
1240+
1241+
if (didChangeCamera
1242+
&& [self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
1243+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera])
1244+
{
1245+
self.camera = oldCamera;
1246+
}
12371247
}
12381248

12391249
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch

platform/ios/src/MGLMapViewDelegate.h

+19
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,25 @@ NS_ASSUME_NONNULL_BEGIN
5959
*/
6060
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
6161

62+
/**
63+
Asks the delegate whether the map view should be allowed to change from the
64+
existing camera to the new camera in response to a user gesture.
65+
66+
This method is called as soon as the user gesture is recognized. It is not
67+
called in response to a programmatic camera change, such as by setting the
68+
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
69+
70+
@param mapView The map view that the user is manipulating.
71+
@param oldCamera The camera representing the viewpoint at the moment the
72+
gesture is recognized. If this method returns `NO`, the map view’s camera
73+
continues to be this camera.
74+
@param newCamera The expected camera after the gesture completes. If this
75+
method returns `YES`, this camera becomes the map view’s camera.
76+
@return A Boolean value indicating whether the map view should stay at
77+
`oldCamera` or change to `newCamera`.
78+
*/
79+
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
80+
6281
#pragma mark Loading the Map
6382

6483
/**

platform/macos/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Right-clicking to open MGLMapView’s context menu no longer prevents the user from subsequently panning the map by clicking and dragging. ([#5593](https://github.com/mapbox/mapbox-gl-native/pull/5593))
66
* Fixed an issue causing overlapping polylines and polygons to be drawn in undefined z-order. Shapes are always drawn in the order they are added to the map, from the oldest on the bottom to the newest on the top. ([#5710](https://github.com/mapbox/mapbox-gl-native/pull/5710))
77
* Improved the design of the generated API documentation. ([#5306](https://github.com/mapbox/mapbox-gl-native/pull/5306))
8+
* Added a method to MGLMapViewDelegate, `-mapView:shouldChangeFromCamera:toCamera:`, that you can implement to restrict which parts the user can navigate to using gestures. ([#5584](https://github.com/mapbox/mapbox-gl-native/pull/5584))
89
* As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143))
910
* Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628))
1011
* Fixed an issue causing polyline and polygon annotations to disappear when the zoom level is one less than the maximum zoom level. ([#5418](https://github.com/mapbox/mapbox-gl-native/pull/5418))

platform/macos/src/MGLMapView.mm

+32
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,13 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate animated:(B
901901
- (void)offsetCenterCoordinateBy:(NSPoint)delta animated:(BOOL)animated {
902902
[self willChangeValueForKey:@"centerCoordinate"];
903903
_mbglMap->cancelTransitions();
904+
MGLMapCamera *oldCamera = self.camera;
904905
_mbglMap->moveBy({ delta.x, delta.y },
905906
MGLDurationInSeconds(animated ? MGLAnimationDuration : 0));
907+
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
908+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
909+
self.camera = oldCamera;
910+
}
906911
[self didChangeValueForKey:@"centerCoordinate"];
907912
}
908913

@@ -949,8 +954,13 @@ - (void)zoomBy:(double)zoomDelta animated:(BOOL)animated {
949954
- (void)scaleBy:(double)scaleFactor atPoint:(NSPoint)point animated:(BOOL)animated {
950955
[self willChangeValueForKey:@"centerCoordinate"];
951956
[self willChangeValueForKey:@"zoomLevel"];
957+
MGLMapCamera *oldCamera = self.camera;
952958
mbgl::ScreenCoordinate center(point.x, self.bounds.size.height - point.y);
953959
_mbglMap->scaleBy(scaleFactor, center, MGLDurationInSeconds(animated ? MGLAnimationDuration : 0));
960+
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
961+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
962+
self.camera = oldCamera;
963+
}
954964
[self didChangeValueForKey:@"zoomLevel"];
955965
[self didChangeValueForKey:@"centerCoordinate"];
956966
}
@@ -1285,15 +1295,25 @@ - (void)handlePanGesture:(NSPanGestureRecognizer *)gestureRecognizer {
12851295
_directionAtBeginningOfGesture = self.direction;
12861296
_pitchAtBeginningOfGesture = _mbglMap->getPitch();
12871297
} else if (gestureRecognizer.state == NSGestureRecognizerStateChanged) {
1298+
MGLMapCamera *oldCamera = self.camera;
1299+
BOOL didChangeCamera = NO;
12881300
mbgl::ScreenCoordinate center(startPoint.x, self.bounds.size.height - startPoint.y);
12891301
if (self.rotateEnabled) {
12901302
CLLocationDirection newDirection = _directionAtBeginningOfGesture - delta.x / 10;
12911303
[self willChangeValueForKey:@"direction"];
12921304
_mbglMap->setBearing(newDirection, center);
1305+
didChangeCamera = YES;
12931306
[self didChangeValueForKey:@"direction"];
12941307
}
12951308
if (self.pitchEnabled) {
12961309
_mbglMap->setPitch(_pitchAtBeginningOfGesture + delta.y / 5, center);
1310+
didChangeCamera = YES;
1311+
}
1312+
1313+
if (didChangeCamera
1314+
&& [self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
1315+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
1316+
self.camera = oldCamera;
12971317
}
12981318
}
12991319
} else if (self.scrollEnabled) {
@@ -1333,7 +1353,12 @@ - (void)handleMagnificationGesture:(NSMagnificationGestureRecognizer *)gestureRe
13331353
if (gestureRecognizer.magnification > -1) {
13341354
[self willChangeValueForKey:@"zoomLevel"];
13351355
[self willChangeValueForKey:@"centerCoordinate"];
1356+
MGLMapCamera *oldCamera = self.camera;
13361357
_mbglMap->setScale(_scaleAtBeginningOfGesture * (1 + gestureRecognizer.magnification), center);
1358+
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
1359+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
1360+
self.camera = oldCamera;
1361+
}
13371362
[self didChangeValueForKey:@"centerCoordinate"];
13381363
[self didChangeValueForKey:@"zoomLevel"];
13391364
}
@@ -1408,9 +1433,16 @@ - (void)handleRotationGesture:(NSRotationGestureRecognizer *)gestureRecognizer {
14081433
_mbglMap->setGestureInProgress(true);
14091434
_directionAtBeginningOfGesture = self.direction;
14101435
} else if (gestureRecognizer.state == NSGestureRecognizerStateChanged) {
1436+
MGLMapCamera *oldCamera = self.camera;
1437+
14111438
NSPoint rotationPoint = [gestureRecognizer locationInView:self];
14121439
mbgl::ScreenCoordinate center(rotationPoint.x, self.bounds.size.height - rotationPoint.y);
14131440
_mbglMap->setBearing(_directionAtBeginningOfGesture + gestureRecognizer.rotationInDegrees, center);
1441+
1442+
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
1443+
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
1444+
self.camera = oldCamera;
1445+
}
14141446
} else if (gestureRecognizer.state == NSGestureRecognizerStateEnded
14151447
|| gestureRecognizer.state == NSGestureRecognizerStateCancelled) {
14161448
_mbglMap->setGestureInProgress(false);

platform/macos/src/MGLMapViewDelegate.h

+19
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,25 @@ NS_ASSUME_NONNULL_BEGIN
6363
*/
6464
- (void)mapView:(MGLMapView *)mapView cameraDidChangeAnimated:(BOOL)animated;
6565

66+
/**
67+
Asks the delegate whether the map view should be allowed to change from the
68+
existing camera to the new camera in response to a user gesture.
69+
70+
This method is called as soon as the user gesture is recognized. It is not
71+
called in response to a programmatic camera change, such as by setting the
72+
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
73+
74+
@param mapView The map view that the user is manipulating.
75+
@param oldCamera The camera representing the viewpoint at the moment the
76+
gesture is recognized. If this method returns `NO`, the map view’s camera
77+
continues to be this camera.
78+
@param newCamera The expected camera after the gesture completes. If this
79+
method returns `YES`, this camera becomes the map view’s camera.
80+
@return A Boolean value indicating whether the map view should stay at
81+
`oldCamera` or change to `newCamera`.
82+
*/
83+
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
84+
6685
#pragma mark Loading the Map
6786

6887
/**

0 commit comments

Comments
 (0)