Viewport
A viewport typically refers to the visible area of a map or scene that is currently being displayed. Our ViewportManager
offers an extensive high-level API for controlling a map's camera. It provides built-in states for following the location puck and showing an overview of a GeoJSON geometry. Transitions between states can be animated with one of the built-in transitions or with custom transitions.
To configure the ViewportManager
, you can update its options
. For example, if you want to take the safe area inset into account when calculating a viewport camera, you can set mapview.viewport.options.usesSafeAreaInsetsAsPadding
to true
.
Viewport status
At any given time, a ViewportStatus
can be either of the followings:
- Idle (camera is not updating)
- Running in a state (an overview viewport or a viewport that is following a location's puck)
- Transitioning to a new state
Note that if you want to use other APIs to control the map's camera i.e
MapboxMap.setCamera(to:)
,
it's a good practice to make sure that the map's viewport is in an idle state.
Listen to viewport status's changes
You can get the current ViewportStatus
by accessing ViewportManager.status
. To get notified when the viewport status changed, you can provide your own implementation of ViewportStatusObserver
and register it to the viewport manager using ViewportManager.addStatusObserver(_:)
Map's viewport manager will keep a strong reference to its status observers, therefore, when you no longer need to listen to viewport status's changes, you should unsubscribe using ViewportManager.removeStatusObserver(_:)
to release this strong reference.
Observers are notified of status changes asynchronously on the main queue. This means that by the time the notification is delivered, the status may have already changed again. This behavior is necessary to allow observers to trigger further transitions while avoiding out-of-order delivery of status changed notifications.
Viewport state
Overview Viewport
An OverviewViewportState
shows a map camera that overviews a region defined by a geometry.
Map(initialViewport: .overview(
geometry: LineString(lineCoordinates),
geometryPadding: UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40))
)
let routeLine = LineString(lineCoordinates)
// Defines a viewport that fits a given geometry with 40px padding from all edges.
let viewportStateOptions = OverviewViewportStateOptions(
geometry: routeLine,
geometryPadding: UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40)
)
// Creates an OverviewViewportState
let overviewViewportState = mapView.viewport.makeOverviewViewportState(options: viewportStateOptions)
// Sets viewport state
mapView.viewport.transition(to: overviewViewportState)
Follow Puck Viewport
A FollowPuckViewportState
shows a map camera that tracks user's location.
Users must grant permission before an app can access information about their location. For more information about asking for the user’s location, see the User location guide.
Map(initialViewport: .followPuck(zoom: 16.35, bearing: .course, pitch: 45))
let followPuckViewportStateOptions = FollowPuckViewportStateOptions(
bearing: .course, // Tells viewport to update its camera's bearing based on current course
pitch: 45,
)
let followPuckViewportState = mapView.viewport.makeFollowPuckViewportState(options: followPuckViewportStateOptions)
// Sets viewport state
mapView.viewport.transition(to: overviewViewportState)
Viewport transitions
The Mapbox Maps SDK provides a way to smoothly transition between different viewport states, either with animations or none. This can enhance the user experience by providing a smooth visual transition between different map views.
The SDK provides 2 implementations of ViewportTransition
: DefaultViewportTransition
and ImmediateViewportTransition
. To transition between viewport states, you first create an instance of the transition, and pass it to ViewportManager.transition(to:transition:completion:)
.
Immediate transition
Like the name suggested, ImmediateViewportTransition
will transition immediately to the new viewport without any animation.
@State vart viewport = Viewport.camera()
Map(viewport: $viewport)
.onAppear {
viewport = .camera(zoom: 4)
}
let immediateTransition = mapview.viewport.makeImmediateViewportTransition()
mapview.viewport.transition(to: newViewportState, transition: immediateTransition)
Default transition
DefaultViewportTransition
transitions between viewport states using an animation that offers cubic bezier easing. This is the default behavior of ViewportManager
when transitioning between states.
You can use convenience method ViewportManager.makeDefaultViewportTransition(options:)
to create an instance of this transition. Optionally you can set a maxDuration
for the transition.
@State vart viewport = Viewport.camera()
Map(viewport: $viewport)
.onAppear {
withViewportAnimation(.default(maxDuration: 2)) {
viewport = .camera(zoom: 4)
}
}
let defaultTransitionOptions = DefaultViewportTransitionOptions(maxDuration: 2) // If maxDuration is not defined, default value 3.5ms will be used.
let defaultTransition = mapview.viewport.makeDefaultViewportTransition(options: defaultTransitionOptions)
mapview.viewport.transition(to: newViewportState, transition: defaultTransition)
Note that any usage of Camera Animator before the map view is moved to new window and the display link is created is invalid, all animators will be marked as completed immediately.
Customize Viewport state and transition
When developing the Mapbox Maps SDK, we emphasized the flexibility for developers to customize our maps, enabling you to achieve precisely tailored functionalities for your application. You can provide a custom implementation for ViewportState
and ViewportTransition
to handle advanced use cases not covered by the provided implementations.
To decrease delays when becoming current, states should generally pre-warm their data sources as soon as they are created. Keep alive only the states that are currently (or soon-to-be) needed to release unneeded resources, such as location services.