Skip to main content

Overview

The camera controls the map’s viewport, including position, zoom level, rotation, and viewing angle. Open Mobile Maps provides different camera APIs for UIKit and SwiftUI.

SwiftUI Camera

In SwiftUI, the camera is managed through a binding to MapView.Camera.

Camera Initialization

@State private var camera = MapView.Camera(
    latitude: 46.962592372639634,
    longitude: 8.378232525377973,
    zoom: 1000000
)
latitude
Double
required
Latitude coordinate of the camera center position
longitude
Double
required
Longitude coordinate of the camera center position
zoom
Double
required
Zoom level (higher values = closer view)

Binding to MapView

MapView(
    camera: $camera,
    layers: layers
)
The camera binding is two-way:
  • Read: Observe camera changes as users interact with the map
  • Write: Programmatically change camera position by updating the binding

Programmatic Camera Updates

struct ContentView: View {
    @State private var camera = MapView.Camera(
        latitude: 46.962592372639634,
        longitude: 8.378232525377973,
        zoom: 1000000
    )
    @State private var layers: [any Layer] = []
    
    var body: some View {
        VStack {
            MapView(
                camera: $camera,
                layers: layers
            )
            
            Button("Zoom In") {
                camera = MapView.Camera(
                    latitude: camera.center.value?.lat ?? 0,
                    longitude: camera.center.value?.lon ?? 0,
                    zoom: (camera.zoom.value ?? 1000000) / 2
                )
            }
        }
        .onAppear {
            setupLayers()
        }
    }
    
    private func setupLayers() {
        layers = [
            TiledRasterLayer("osm", webMercatorUrlFormat: "https://tiles.sample.org/{z}/{x}/{y}.png")
        ]
    }
}

UIKit Camera

In UIKit, camera operations are performed through MCMapCameraInterface accessible via mapView.camera.

MCMapCameraInterface

class MapViewController: UIViewController {
    lazy var mapView = MCMapView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Access camera interface
        let camera = mapView.camera
    }
}

Move to Position

Move the camera to a specific coordinate and zoom level:
mapView.camera.move(
    toCenterPositionZoom: MCCoord(lat: 46.962592372639634, lon: 8.378232525377973),
    zoom: 1000000,
    animated: true
)
toCenterPositionZoom
MCCoord
required
Target center position for the camera
zoom
Double
required
Target zoom level
animated
Bool
default:"false"
Whether to animate the camera movement

Camera Movement Examples

Move to Location (Animated)

mapView.camera.move(
    toCenterPositionZoom: MCCoord(lat: 47.3769, lon: 8.5417),
    zoom: 500000,
    animated: true
)

Move to Location (Instant)

mapView.camera.move(
    toCenterPositionZoom: MCCoord(lat: 47.3769, lon: 8.5417),
    zoom: 500000,
    animated: false
)

Get Current Camera State

Access the current camera position and zoom level:
let camera = mapView.camera
let currentPosition = camera.centerPosition
let currentZoom = camera.zoom

Coordinate System

MCCoord

Coordinates can be created using latitude/longitude:
let coord = MCCoord(lat: 46.962592372639634, lon: 8.378232525377973)
Or with a specific coordinate system identifier:
let coord = MCCoord(
    systemIdentifier: MCCoordinateSystemIdentifiers.epsg3857(),
    x: -20037508.34,
    y: 20037508.34,
    z: 0.0
)
lat
Double
required
Latitude coordinate in WGS84
lon
Double
required
Longitude coordinate in WGS84
systemIdentifier
Int32
Coordinate system identifier (e.g., EPSG:3857)
x
Double
X coordinate in the specified coordinate system
y
Double
Y coordinate in the specified coordinate system
z
Double
Z coordinate (elevation)

Zoom Levels

Zoom levels in Open Mobile Maps are numeric values where:
  • Higher values = closer/more detailed view
  • Lower values = farther/less detailed view
Common zoom level examples:
  • 1000000 - City level view
  • 500000 - Zoomed in city view
  • 100000 - Street level view
  • 50000 - Building level view

Best Practices

Animated Transitions

Use animated camera movements for better user experience:
// Good: Smooth transition
mapView.camera.move(
    toCenterPositionZoom: newLocation,
    zoom: newZoom,
    animated: true
)

// Avoid: Jarring instant jump (unless intentional)
mapView.camera.move(
    toCenterPositionZoom: newLocation,
    zoom: newZoom,
    animated: false
)

Initial Camera Position

Set the initial camera position after adding layers:
override func viewDidLoad() {
    super.viewDidLoad()
    
    // Add layers first
    mapView.add(layer: TiledRasterLayer("osm", webMercatorUrlFormat: "https://tiles.sample.org/{z}/{x}/{y}.png"))
    
    // Then set initial camera position
    mapView.camera.move(
        toCenterPositionZoom: MCCoord(lat: 46.962592372639634, lon: 8.378232525377973),
        zoom: 1000000,
        animated: false
    )
}

SwiftUI Camera Synchronization

When using UIViewRepresentable to wrap MCMapView in SwiftUI, sync the initial camera position:
func makeUIView(context: Context) -> MCMapView {
    let mapView = MCMapView()
    
    // Add layers
    mapView.add(layer: TiledRasterLayer("osm", webMercatorUrlFormat: "https://tiles.sample.org/{z}/{x}/{y}.png"))
    
    // Sync with SwiftUI camera state
    if let center = camera.center.value, let zoom = camera.zoom.value {
        mapView.camera.move(toCenterPositionZoom: center, zoom: zoom, animated: false)
    }
    
    return mapView
}

Build docs developers (and LLMs) love