notnoop
notnoop

Reputation: 59299

Rotate MapView using Compass orientation

Is it possible to have an embedded MKMapView rotate to always face the direction the iPhone is facing? Basically I want to mimic the Map app rotation feature on my own app.

I see that the iPhone SDK does not expose the functionality. However, I wonder if it would work to rotate the entire view using CGAffineTransformMakeRotate. Would it affect tapping and zooming? Is there a better way?

Upvotes: 7

Views: 19222

Answers (5)

Andy
Andy

Reputation: 876

Simple solution in swift 3.0. Make sure to put the line in mapViewDidFinishLoadingMap or it will ignore it

public func mapViewDidFinishLoadingMap(_ mapView: MKMapView)
{
    mapView.setUserTrackingMode(.followWithHeading, animated: false)
}

If you don't want the map to center on the user location you might do something like this

public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
{
    if(CLLocationCoordinate2DIsValid(mapView.centerCoordinate))
    {
        mapView.camera.heading = newHeading.trueHeading
    }
}

Upvotes: 2

oscar castellon
oscar castellon

Reputation: 3138

if you use a navigationVontroller try this:

//For Left button
 MKUserTrackingBarButtonItem *buttonItem = [[MKUserTrackingBarButtonItem 
                                                 alloc]initWithMapView:_mapView];

 self.navigationItem.leftBarButtonItem = buttonItem;


// For Right Button
     MKUserTrackingBarButtonItem *buttonItem = [[MKUserTrackingBarButtonItem 
                                                     alloc]initWithMapView:_mapView];

     self.navigationItem.rightBarButtonItem = buttonItem;

Upvotes: -2

thijsai
thijsai

Reputation: 1785

To rotate the mapView but not the annotations you could use the following code to compensate for the maps rotation.

- (void)locationManager:(CLLocationManager *)manager
       didUpdateHeading:(CLHeading *)newHeading
{
  double rotation = newHeading.magneticHeading * 3.14159 / 180;
  CGPoint anchorPoint = CGPointMake(0, -23); // The anchor point for your pin

  [mapView setTransform:CGAffineTransformMakeRotation(-rotation)];

  [[mapView annotations] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    MKAnnotationView * view = [mapView viewForAnnotation:obj];

    [view setTransform:CGAffineTransformMakeRotation(rotation)];
    [view setCenterOffset:CGPointApplyAffineTransform(anchorPoint, CGAffineTransformMakeRotation(rotation))];

  }];

}

Another sollution is using a new method that has been added in iOS 5 to MKMapView.

Take a look at: http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html

- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;

Upvotes: 13

Doug Hays
Doug Hays

Reputation: 1507

I can confirm that it works fine. Here's the code that I'm using:

[mapView setTransform:CGAffineTransformMakeRotation(-1 * currentHeading.magneticHeading * 3.14159 / 180)];

mapView is my MKMapView instance

Upvotes: 8

Ramin
Ramin

Reputation: 13433

If you look in the 3.0 iPhone Application Programming Guide under Device Support you'll find information on the magnetometer (aka compass). Once you start getting heading information (through the didUpdateHeading method) you should be able to get the compass data then use that to calculate the proper rotation transform value to apply to the map view.

Not sure if it handles zooming. In the standard map application I've noticed that compass heading tracking stops as soon as you start pinch-zooming.

Also, keep in mind that location directions are in degrees whereas transform rotation angles are in radians.

Upvotes: 1

Related Questions