> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/ios/maps/llms.txt)

# Adjust the Map's Viewport

Your browser doesn't support HTML5 video. Open [link to the video](https://docs.mapbox.com/ios/ios/assets/medias/ViewportCamera-eb45b4c0aab761900ace9ba34c662405.mp4).

This example demonstrates the usage of [`viewport`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/mapview/viewport/) provided by the **Mapbox Maps SDK for iOS**. Viewport is used to support camera synchronization with the puck, display an overview of a region, and switch between the two states using transitions. The example includes logic to handle two states: following the puck and displaying an overview. By toggling between the `following` and `overview` states, users can experience different viewpoints within the map. It is recommended to try this example in a simulator by selecting Features > Location > Freeway Drive to see the resulting user experience.

The example utilizes classes such as [`FollowPuckViewportState`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/followpuckviewportstate/) for the following state and [`OverviewViewportState`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/overviewviewportstate/) for the overview state, each configured with specific options. Additionally, the implementation involves observing changes in the viewport status through the [`ViewportStatusObserver`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/viewportstatusobserver/) protocol, providing insights into viewport status transitions.

> **Note: iOS Examples App Available**
> 
> This example code is part of the **Maps SDK for iOS Examples App**, a working iOS project [available on Github](https://github.com/mapbox/mapbox-maps-ios/tree/11.31.0/Sources/Examples). iOS developers are encouraged to run the examples app locally to interact with this example in an emulator and explore other features of the Maps SDK.
> 
> See our [Run the Maps SDK for iOS Examples App](https://docs.mapbox.com/help/tutorials/maps-sdk-ios-examples-app/) tutorial for step-by-step instructions.

**Swift**

Title: `ViewportExample.swift`

[View on GitHub](https://github.com/mapbox/mapbox-maps-ios/blob/main/Sources/Examples/All%20Examples/ViewportExample.swift)

```swift
import UIKit
import MapboxMaps

// This example shows how to use the viewport API to keep the camera in sync with the puck,
// show an overview of a region, and toggle between those states with transitions.
//
// When trying this example in the simulator, choose Features > Location > Freeway Drive
// to get a good sense of the resulting user experience.
final class ViewController: UIViewController {
    private enum State {
        case following
        case overview
    }

    private var state: State = .following {
        didSet {
            syncWithState()
        }
    }

    private var viewportButton = UIButton(type: .system)
    private var mapView: MapView!
    private var followPuckViewportState: FollowPuckViewportState!
    private var overviewViewportState: OverviewViewportState!

    override func viewDidLoad() {
        super.viewDidLoad()

        mapView = MapView(frame: view.bounds)
        view.addSubview(mapView)

        let cupertino = CLLocationCoordinate2D(latitude: 37.3230, longitude: -122.0322)

        mapView.mapboxMap.setCamera(to: CameraOptions(center: cupertino, zoom: 14))

        mapView.location.options.puckType = .puck2D(.makeDefault(showBearing: true))
        mapView.location.options.puckBearing = .heading
        mapView.location.options.puckBearingEnabled = true

        followPuckViewportState = mapView.viewport.makeFollowPuckViewportState(
            options: FollowPuckViewportStateOptions(
                bearing: .heading))

        overviewViewportState = mapView.viewport.makeOverviewViewportState(
            options: OverviewViewportStateOptions(
                geometry: Polygon(
                    center: cupertino,
                    radius: 20000,
                    vertices: 100)))

        viewportButton.translatesAutoresizingMaskIntoConstraints = false
        viewportButton.backgroundColor = .systemBackground
        viewportButton.contentEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
        view.addSubview(viewportButton)
        NSLayoutConstraint.activate([
            viewportButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            viewportButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)])
        viewportButton.addTarget(
            self,
            action: #selector(toggleViewportState),
            for: .touchUpInside)

        syncWithState()
    }

    

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // break strong reference cycle
        mapView.viewport.removeStatusObserver(self)
    }

    @objc private func toggleViewportState() {
        switch state {
        case .overview:
            state = .following
        case .following:
            state = .overview
        }
    }

    private func syncWithState() {
        switch state {
        case .following:
            mapView.viewport.transition(to: followPuckViewportState)
            viewportButton.setTitle("Overview", for: .normal)
        case .overview:
            mapView.viewport.transition(to: overviewViewportState)
            viewportButton.setTitle("Follow", for: .normal)
        }
    }
}

extension ViewController: ViewportStatusObserver {
    func viewportStatusDidChange(
        from fromStatus: ViewportStatus,
        to toStatus: ViewportStatus,
        reason: ViewportStatusChangeReason) {
            print("Viewport.status changed\n    from: \(fromStatus)\n    to: \(toStatus)\n    with reason: \(reason)")
    }
}
```