Skip to content

Commit

Permalink
Add iOS example for constraining map to certain area (maplibre#2392)
Browse files Browse the repository at this point in the history
  • Loading branch information
louwers authored May 13, 2024
1 parent 29ccd3f commit 8e479ee
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 2 deletions.
61 changes: 61 additions & 0 deletions platform/ios/MapLibre.docc/BlockingGesturesExample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Blocking Gestures

Constrain the map to a certain area.

## Overview

To constrain the map to a certain area, you need to implement the ``MLNMapViewDelegate/mapView:shouldChangeFromCamera:toCamera:`` method of ``MLNMapViewDelegate``. By returning a boolean you can either allow or disallow a camera change.

<!-- include-example(BlockingGesturesExample) -->

```swift
// Denver, Colorado
private let center = CLLocationCoordinate2D(latitude: 39.748947, longitude: -104.995882)

// Colorado’s bounds
private let colorado = MLNCoordinateBounds(
sw: CLLocationCoordinate2D(latitude: 36.986207, longitude: -109.049896),
ne: CLLocationCoordinate2D(latitude: 40.989329, longitude: -102.062592)
)

struct BlockingGesturesExample: UIViewRepresentable {
class Coordinator: NSObject, MLNMapViewDelegate {
func mapView(_ mapView: MLNMapView, shouldChangeFrom _: MLNMapCamera, to newCamera: MLNMapCamera) -> 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 = MLNCoordinateInCoordinateBounds(newCameraCenter, colorado)
let intersects = MLNCoordinateInCoordinateBounds(newVisibleCoordinates.ne, colorado) && MLNCoordinateInCoordinateBounds(newVisibleCoordinates.sw, colorado)

return inside && intersects
}
}

func makeUIView(context: Context) -> MLNMapView {
let mapView = MLNMapView(frame: .zero, styleURL: VERSATILES_COLORFUL_STYLE)
mapView.setCenter(center, zoomLevel: 10, direction: 0, animated: false)
mapView.delegate = context.coordinator

return mapView
}

func updateUIView(_: MLNMapView, context _: Context) {}

func makeCoordinator() -> Coordinator {
Coordinator()
}
}
```

The style used in this example can be found here: <doc:ExampleStyles>.
9 changes: 9 additions & 0 deletions platform/ios/MapLibre.docc/ExampleStyles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Styles in Examples

The following styles are used in the examples:

<!-- include-example(ExampleStyles) -->

```swift
let VERSATILES_COLORFUL_STYLE = URL(string: "https://tiles.versatiles.org/assets/styles/colorful.json")
```
1 change: 1 addition & 0 deletions platform/ios/MapLibre.docc/MapLibre.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Powerful, free and open-source mapping toolkit with full control over data sourc
- <doc:GettingStarted>
- <doc:LineOnUserTap>
- <doc:LocationPrivacyExample>
- <doc:BlockingGesturesExample>

## Topics

Expand Down
54 changes: 54 additions & 0 deletions platform/ios/app-swift/Sources/BlockingGesturesExample.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import MapLibre
import SwiftUI
import UIKit

// #-example-code(BlockingGesturesExample)
// Denver, Colorado
private let center = CLLocationCoordinate2D(latitude: 39.748947, longitude: -104.995882)

// Colorado’s bounds
private let colorado = MLNCoordinateBounds(
sw: CLLocationCoordinate2D(latitude: 36.986207, longitude: -109.049896),
ne: CLLocationCoordinate2D(latitude: 40.989329, longitude: -102.062592)
)

struct BlockingGesturesExample: UIViewRepresentable {
class Coordinator: NSObject, MLNMapViewDelegate {
func mapView(_ mapView: MLNMapView, shouldChangeFrom _: MLNMapCamera, to newCamera: MLNMapCamera) -> 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 = MLNCoordinateInCoordinateBounds(newCameraCenter, colorado)
let intersects = MLNCoordinateInCoordinateBounds(newVisibleCoordinates.ne, colorado) && MLNCoordinateInCoordinateBounds(newVisibleCoordinates.sw, colorado)

return inside && intersects
}
}

func makeUIView(context: Context) -> MLNMapView {
let mapView = MLNMapView(frame: .zero, styleURL: VERSATILES_COLORFUL_STYLE)
mapView.setCenter(center, zoomLevel: 10, direction: 0, animated: false)
mapView.delegate = context.coordinator

return mapView
}

func updateUIView(_: MLNMapView, context _: Context) {}

func makeCoordinator() -> Coordinator {
Coordinator()
}
}

// #-end-example-code
3 changes: 3 additions & 0 deletions platform/ios/app-swift/Sources/MapLibreNavigationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ struct MapLibreNavigationView: View {
NavigationLink("LocationPrivacyExample") {
LocationPrivacyExampleView()
}
NavigationLink("BlockingGesturesExample") {
BlockingGesturesExample()
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions platform/ios/app-swift/Sources/Styles.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

// #-example-code(ExampleStyles)

let VERSATILES_COLORFUL_STYLE = URL(string: "https://tiles.versatiles.org/assets/styles/colorful.json")

// #-end-example-code
3 changes: 1 addition & 2 deletions platform/ios/src/MLNMapViewDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
`oldCamera` or change to `newCamera`.
#### Related examples
TODO: Restrict map panning to an area, learn how to use this method
and `MLNMapCamera` objects to restrict a users ability to pan your map.
- <doc:BlockingGesturesExample>
*/
- (BOOL)mapView:(MLNMapView *)mapView shouldChangeFromCamera:(MLNMapCamera *)oldCamera toCamera:(MLNMapCamera *)newCamera;

Expand Down

0 comments on commit 8e479ee

Please sign in to comment.