MapCameraBounds limits where the map camera can go, and MapCameraPosition is the two-way
binding that reads and drives it. Together they keep the user inside your area and your code in
control of the viewport.
Bounding the Map
Build a MapCameraBounds from an MKMapRect or MKCoordinateRegion. The user cannot pan
outside it. The minimumDistance and maximumDistance parameters clamp zoom, in meters.
let rect = MKMapRect(
origin: MKMapPoint(.newYork),
size: MKMapSize(width: 1, height: 1)
)
Map(
bounds: MapCameraBounds(
centerCoordinateBounds: rect,
minimumDistance: 10,
maximumDistance: 100
)
) {
Marker("New York", monogram: Text("NY"), coordinate: .newYork)
}
MKMapRect measures in map points, a flat 2D projection; MKMapPoint converts between
coordinates and map points. Use MKCoordinateRegion instead when you prefer latitude and
longitude deltas.
A Rect That Fits All Markers
To bound the map around a set of coordinates, union one small rect per coordinate.
let coordinates: [CLLocationCoordinate2D] = [.newYork, .sanFrancisco, .seattle]
let rect = coordinates
.map { MKMapRect(origin: .init($0), size: .init(width: 1, height: 1)) }
.reduce(MKMapRect.null) { $0.union($1) }
Driving the Camera
MapCameraPosition builds from a camera, rect, region, item, or the user location. Setting the
bound state moves the camera; the user dragging the map writes back into it.
@State private var position: MapCameraPosition = .camera(
.init(centerCoordinate: .newYork, distance: 0)
)
Map(position: $position) { /* content */ }
.onAppear {
position = .camera(.init(centerCoordinate: .sanFrancisco, distance: 0))
}
userLocation(followsHeading:fallback:) keeps the camera on the user, rotating with their
heading, and falls back when location is unavailable.
Reading the Position Back
The position exposes optional camera, region, and rect values; each is non-nil only when
that representation is in use. positionedByUser tells you whether the user moved the camera or
your code did, which is the flag to check before recentering.
.onChange(of: position) {
print(position.positionedByUser)
print(position.camera as Any)
}