Flyover Map using MapKit in SwiftUI

DevTechie Inc
May 11, 2023

MapKit and Apple Map provides the ability to flyover major cities and landmarks. Flyover feature is interactive to panzoom and rotate around the landmarks. We use satelliteFlyover MapType and MKMapCamera to build flyover feature.

Today we will flyover Statue of Liberty using MapKit.

Let’s get started.

Since SwiftUI’s MapView doesn’t support Map Camera yet, we will cross over to the UIKit side and bring the functionality over via UIViewRepresentable

We will create a MapView conforming to the UIViewRepresentable protocol.

struct MapView: UIViewRepresentable {
    
    let distance: CLLocationDistance = 200
    let pitch: CGFloat = 400
    let heading = 90.0
    let coordinate = CLLocationCoordinate2DMake(40.68924124412252, -74.04457550374869)
    
    func makeUIView(context: Context) -> MKMapView {
       
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {}
}

Distance, pitch and heading are required by MKMapCamera

MKMapCamera is a virtual camera for defining the appearance of the map. Initializer we are gonna use takes following parameters.

centerCoordinate the coordinate point on which the map should be centered.

distance the line-of-sight distance from the camera to the center coordinate of the map.

pitch the viewing angle of the camera, measured in degrees. A value of 0results in a camera pointed straight down at the map. Angles greater than 0result in a camera that is pitched toward the horizon by the specified number of degrees.

heading the heading of the camera (measured in degrees) relative to true north. The value 0means that the top edge of the map view corresponds to true north. The value 90 means the top of the map is pointing due east. The value 180 means the top of the map points due south, and so on.

struct MapView: UIViewRepresentable {
    
    let distance: CLLocationDistance = 200
    let pitch: CGFloat = 400
    let heading = 90.0
    let coordinate = CLLocationCoordinate2DMake(40.68924124412252, -74.04457550374869)
    
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.mapType = .satelliteFlyover
        
        let camera = MKMapCamera(lookingAtCenter: coordinate, fromDistance: distance, pitch: pitch, heading: heading)
        mapView.camera = camera
        return mapView
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {}
}

Use the MapView inside another view.

struct DevTechieFlyoverMap: View {
    var body: some View {
        MapView()
            .ignoresSafeArea()
    }
}