Back to examples
intermediate

Restrict map panning to an area

Prevent a map from being panned to a different place by constraining the viewport.

      

import Mapbox

class ViewController: UIViewController, MGLMapViewDelegate {
    
    private var colorado: MGLCoordinateBounds!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.delegate = self
        
        // Denver, Colorado
        let center = CLLocationCoordinate2D(latitude: 39.748947, longitude: -104.995882)
        
        // Starting point
        mapView.setCenter(center, zoomLevel: 10, direction: 0, animated: false)
        
        // Colorado’s bounds
        let ne = CLLocationCoordinate2D(latitude: 40.989329, longitude: -102.062592)
        let sw = CLLocationCoordinate2D(latitude: 36.986207, longitude: -109.049896)
        colorado = MGLCoordinateBounds(sw: sw, ne: ne)
        
        view.addSubview(mapView)
    }
    
    // This example uses Colorado’s boundaries to restrict the camera movement.
    func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera) -> Bool {
        
        // Get the current camera to restore it after.
        let currentCamera = mapView.camera
        
        // From the new camera obtain the center to test if it’s inside the boundaries.
        let newCameraCenter = newCamera.centerCoordinate

        // Set the map’s visible bounds to newCamera.
        mapView.camera = newCamera
        let newVisibleCoordinates = mapView.visibleCoordinateBounds
        
        // Revert the camera.
        mapView.camera = currentCamera

        // Test if the newCameraCenter and newVisibleCoordinates are inside self.colorado.
        let inside = MGLCoordinateInCoordinateBounds(newCameraCenter, self.colorado)
        let intersects = MGLCoordinateInCoordinateBounds(newVisibleCoordinates.ne, self.colorado) && MGLCoordinateInCoordinateBounds(newVisibleCoordinates.sw, self.colorado)
        
        return inside && intersects
    }
}




      
      


#import "ViewController.h"
@import Mapbox;

@interface ViewController () <MGLMapViewDelegate>
@property (nonatomic) MGLCoordinateBounds colorado;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
    mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    mapView.delegate = self;
    mapView.styleURL = [MGLStyle outdoorsStyleURL];
    
    // Denver, Colorado
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(39.748947, -104.995882);
    
    // Starting point
    [mapView setCenterCoordinate:center zoomLevel:10 direction:0 animated:NO];
    
    // Colorado’s bounds
    CLLocationCoordinate2D ne = CLLocationCoordinate2DMake(40.989329, -102.062592);
    CLLocationCoordinate2D sw = CLLocationCoordinate2DMake(36.986207, -109.049896);
    self.colorado = MGLCoordinateBoundsMake(sw, ne);
    
    [self.view addSubview:mapView];
}

// This example uses Colorado’s boundaries to restrict the camera movement.

- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera {
    // Get the current camera to restore it after.
    MGLMapCamera *currentCamera = mapView.camera;
    
    // From the new camera obtain the center to test if it’s inside the boundaries.
    CLLocationCoordinate2D newCameraCenter = newCamera.centerCoordinate;
    
    // Set the map’s visible bounds to newCamera.
    mapView.camera = newCamera;
    MGLCoordinateBounds newVisibleCoordinates = mapView.visibleCoordinateBounds;
    
    // Revert the camera.
    mapView.camera = currentCamera;
    
    // Test if the newCameraCenter and newVisibleCoordinates are inside self.colorado.
    BOOL inside = MGLCoordinateInCoordinateBounds(newCameraCenter, self.colorado);
    BOOL intersects = MGLCoordinateInCoordinateBounds(newVisibleCoordinates.ne, self.colorado) && MGLCoordinateInCoordinateBounds(newVisibleCoordinates.sw, self.colorado);
    
    return inside && intersects;
}

@end