mkmapviewmapkitmkmapcamera

MKMapCamera changing heading to look at different map center


I am trying to use an MKMapView and MKMapCamera. So far I was able to setup everything and configure the Map in 3D mode/flyover. I am taking for example for the center of my maps the Empire States Building in NYC, and setup my MKMapCamera with the constructor:

public init(lookingAtCenterCoordinate centerCoordinate:
   CLLocationCoordinate2D, fromDistance distance: CLLocationDistance, 
   pitch: CGFloat, heading: CLLocationDirection)

So I can now see properly at the center the Empire States Building. Now what I would like to be able is to change the 'heading' (CLLocationDirection) of my MKMapCamera to point to a different direction: meaning not having at the center the Empire States Building.

Right now if I change the heading on the camera, it will in fact move the camera around and still keep the Empire States Building at the center of my MKMapView.

Looking at the various API, I can't find what API could be using to 'recompute' the new MKMapView center after changing the heading.

I would like to get the opposite behavior of the current MKMapView where I want my MKMapCamera to be fixed where the center of the map is moving according to the heading I specify.

What will be the proper way to achieve that?


Solution

  • When you change the heading of a MKMapCamera object that is looking at the center of the map, you are changing the angle of rotation of the camera around that center point. Imagine that the camera is tied to the center point with a piece of string. The camera can only move in a circle around the center point. How far the camera moves around the center point is controlled by the heading of the camera. In your example, the center point is the Empire State building so changing the heading of the camera will move the camera around the Empire State Building in a circle while keeping the camera facing the building.

    If I understand your requirement correctly, you want to keep your camera location fixed and change the location shown at the center of the map using a heading from the camera. To accomplish this, you need to calculate a new center coordinate for the map. The new center coordinate will be a point on the circumference of an imaginary circle centered on your camera. The radius of the circle is the distance of the point at the center of the map from the camera.

    This calculation uses the location of the camera, the heading from the camera and the distance from the camera to calculate a latitude and longitude coordinate that will be the new center of the map. GreatCircle is an Objective-C library that provides the locationWithBearing:distance: method as an extension of CLLocation that performs the calculation you need:

    - (nonnull CLLocation *)locationWithBearing:(CLLocationDirection)bearing
                                       distance:(CLLocationDistance)distance;
    

    So, given the location of your camera c, a heading (bearing) h (in degrees) and a distance d (in meters), the new center of the map m will be (in Swift):

    let m = c.locationWithBearing(h, distance: d)