FlyoverKit - 360° flyover on a MKMapView

FlyoverKit enables you to present stunning 360° flyover views on an MKMapView with zero effort while maintaining full configuration possibilities. FlyoverKit builds the core of STLocationRequest which enables you a way to request the user location services via a 3D 360° flyover MapView.

Example

The example Application is an excellent way to see FlyoverKit in action. You get a brief look of the available configuration options and how they affect the flyover behaviour. Simply open the FlyoverKit.xcodeproj and run the FlyoverKit-Example scheme. Please keep in mind that the SatelliteFlyover and HybridFlyover will only work on a real iOS device.

Installation

CocoaPods

FlyoverKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'FlyoverKit'

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

To integrate FlyoverKit into your Xcode project using Carthage, specify it in your Cartfile:

github "SvenTiigi/FlyoverKit"

Run carthage update --platform iOS to build the framework and drag the built FlyoverKit.framework into your Xcode project.

On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase” and add the Framework path as mentioned in Carthage Getting started Step 4, 5 and 6

Swift Package Manager

To integrate using Apple’s Swift Package Manager, add the following as a dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/SvenTiigi/FlyoverKit.git", from: "1.3.1")
]

Manually

If you prefer not to use any of the aforementioned dependency managers, you can integrate FlyoverKit into your project manually. Simply drag the Sources Folder into your Xcode project.

Usage

FlyoverKit can be implemented in three different ways. Simply choose the most suitable type for your implementation. Please see the Advanced section in order to configure the FlyoverKit to your needs.

FlyoverCamera

If you already have a MKMapView in your Controller and you want to add a flyover to this MapView, simply use the FlyoverCamera.

import FlyoverKit

// Initialize the FlyoverCamera with an already existing MKMapView
let flyoverCamera = FlyoverCamera(mapView: self.mapView)

// Initialize a location via CLLocationCoordinate2D
let eiffelTower = CLLocationCoordinate2D(latitude: 48.858370, longitude: 2.294481)

// Start flyover
flyoverCamera.start(flyover: eiffelTower)

FlyoverMapView

If you wish to show a MapView which is already preconfigured to perform a flyover on a given location, you should use the FlyoverMapView.

import FlyoverKit

// Initialize the FlyoverMapView
let flyoverMapView = FlyoverMapView()

// Initialize a location via CLLocation
let eiffelTower = CLLocation(latitude: 48.858370, longitude: 2.294481)

// Start flyover
flyoverMapView.start(flyover: eiffelTower)

FlyoverMapViewController

If you wish to present a UIViewController with an embedded FlyoverMapView to perform a flyover on a given location, FlyoverMapViewController is at your service.

import FlyoverKit

// Initialize a location via FlyoverAwesomePlace
let eiffelTower = FlyoverAwesomePlace.parisEiffelTower

// Initialize the FlyoverMapViewController with a Flyover object
let controller = FlyoverMapViewController(flyover: eiffelTower)

// Present controller
self.present(controller, animated: true)

Advanced

The FlyoverKit consists of three main components. The Flyover protocol, FlyoverCamera and FlyoverMapView

Flyover Protocol

The flyover protocol specifies a type with a CLLocationCoordinat2D property. It is used to perform a flyover on the given coordinate.

public protocol Flyover {
    var coordinate: CLLocationCoordinate2D { get }
}

The FlyoverKit already implemented this protocol to various MapKit and CoreLocation types like CLLocationCoordinate2D, CLLocation, MKMapPoint, MKMapItem, MKCoordinateRegion and many more.

You can apply the Flyover protocol to your own models to use them for a flyover.

struct Address {
    var name: String
    var coordinate: CLLocationCoordinate2D
}
extension Address: Flyover {}

Operators

In order to compare two Flyover types you can use the following two operators.

Equatable operator (==)

self.flyover1 == self.flyover2

Checks if the two given Flyover types are exactly the same via comparison of latitude and longitude.

Rounded Equatable operator (~~)

self.flyover1 ~~ self.flyover2

Checks if the two given Flyover types are nearly the same via comparison of rounded latitude and longitude.

FlyoverAwesomePlace

The FlyoverAwesomePlace is a Flyover protocol compliant Enumeration with awesome locations and landmarks like NewYorkStatueOfLiberty, GooglePlex, SydneyOperaHouse and many more. You can use them in your own implementation or to explore different locations in the FlyoverKitExample Application.

FlyoverCamera

The FlyoverCamera is responsible for manipulating the MKMapView camera and performs a 360° flyover animation via UIViewPropertyAnimator.

In order to initialize a FlyoverCamera object you need to pass a MKMapView (which reference will be weakly stored) and a FlyoverCamera.Configuration object.

// Initialize FlyoverCamera configuration
let configuration = FlyoverCamera.Configuration(
    duration: 4.0,
    altitude: 600.0,
    pitch: 45.0,
    headingStep: 20.0
)

// Initialize FlyoverCamera
let camera = FlyoverCamera(
    mapView: mapView,
    configuration: configuration
)

// Start Flyover
camera.start(flyover: location)

Configuration

The FlyoverCamera.Configuration struct holds all specific flyover configuration values. Set the properties to get the right look and feel of the flyover as you need it to be.

Configuration Description
duration The flyover animation duration
altitude The altitude above the ground, measured in meters
pitch The viewing angle of the camera, measured in degrees
headingStep The direction step in degrees that is added to the MapViewCamera heading in each flyover iteration
regionChangeAnimation The region change animation that should be applied if a flyover has been started and the MapCamera has to change the region. Default is always .none which immediately present the place. If you wish that the region change should be performed via an animation you can set .animated(duration: 1.5, curve: .easeIn)

An excellent visualization of an MKMapCamera from TechTopia

Configuration Theme

If you don’t want to set the properties yourself you can use a preconfigured configuration theme. Currently there are four themes available

Theme Description
default Default flyover configuration with configuration for a default flyover usage
lowFlying Flyover configuration with a low altitude and a high pitch. Simulates a low flying helicopter viewing angle
farAway Configuration with a high altitude and a normal pitch which results in a far away viewing angle
giddy A giddy configuration
?
which you shouldn’t use in production. But it’s fun
?‍♂️

?

astronautView The view of an astronaut
?

Furthermore, you can initialize a FlyoverCamera with a given Theme.

// Initialize FlyoverCamera
let camera = FlyoverCamera(
    mapView: mapView,
    configuration: .default
)

More themes coming soon…
?‍?

FlyoverMapView

The FlyoverMapView is a preconfigured MKMapView with an embedded FlyoverCamera. The FlyoverMapView offers various convenience functions for example starting a flyover with a MKAnnotation object or setting a supported flyover MapType.

// Initialize with default configuration theme and standard MapType
let flyoverMapView = FlyoverMapView()

// Or initialize by setting a different theme and the satelliteFlyover MapType
let flyoverMapView = FlyoverMapView(configuration: .farAway, mapType: .satelliteFlyover)

MapType

The FlyoverMapView.MapType specifies the three supported MKMapType‘s.

MapType Description
standard A street map that shows the position of all roads and shows 3D buildings
satelliteFlyover A satellite image of the area with road and road name information layered on top
hybridFlyover A hybrid satellite image with flyover data where available

FlyoverMapViewController

The FlyoverMapViewController is an easy and simple way to present a UIViewController with an embedded FlyoverMapView. You can use it if you just want to present a 360° flyover on a given Flyover type.

// Initialize a location
let eiffelTower = CLLocationCoordinate2DMake(48.858370, 2.294481)

// Initialize the FlyoverMapViewController with a Flyover object
let controller = FlyoverMapViewController(flyover: eiffelTower)

// Present controller
self.present(controller, animated: true)

Additionally you can initialize the FlyoverMapViewController with your own Configuration or Configuration.Theme and a MapType

// Initialize a location
let eiffelTower = CLLocationCoordinate2DMake(48.858370, 2.294481)

// Initialize a Configuration
let configuration = FlyoverCamera.Configuration(
    duration: 4.0,
    altitude: 600.0,
    pitch: 45.0,
    headingStep: 20.0
)

// Initialize the FlyoverMapViewController
let controller = FlyoverMapViewController(
    flyover: eiffelTower, 
    configuration: configuration, 
    mapType: .satelliteFlyover
)

// Present controller
self.present(controller, animated: true)

Contributing

Contributions are very welcome
?

?

License

FlyoverKit
Copyright (c) 2020 Sven Tiigi <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

GitHub

https://github.com/SvenTiigi/FlyoverKit