30

I want to know the current zoom level of MKMapView in iphone programming, how can I do that? Actually I have one app, that is taking few arguments(Radius from center to corner of MKMapView) are returning the store details in that are, when I am on MKMapView, the radius is very high and it changes when Radius is smaller, so I want to know the zoom level and setup my webservice according to that, How can I get zoom level of current MKMapView visible area?

Surfer
  • 1,370
  • 3
  • 19
  • 34
Chatar Veer Suthar
  • 15,541
  • 26
  • 90
  • 154

5 Answers5

52

I created very simple helper subclass for it:

#define MERCATOR_RADIUS 85445659.44705395
#define MAX_GOOGLE_LEVELS 20

@interface MKMapView (ZoomLevel)
- (double)getZoomLevel;
@end

@implementation MKMapView (ZoomLevel)

- (double)getZoomLevel
{
    CLLocationDegrees longitudeDelta = self.region.span.longitudeDelta;
    CGFloat mapWidthInPixels = self.bounds.size.width;
    double zoomScale = longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapWidthInPixels);
    double zoomer = MAX_GOOGLE_LEVELS - log2( zoomScale );
    if ( zoomer < 0 ) zoomer = 0;
//  zoomer = round(zoomer);
    return zoomer;
}

@end
NiKe
  • 581
  • 1
  • 5
  • 4
  • I think MAX_GOOGLE_LEVELS can be obtained from `MKMapSizeWorld.width / 256` and take the log2 of that where 256 is the tile width or tile height in pixel (or maybe point) – huggie Oct 21 '13 at 07:49
  • That is log2(MKMapSizeWorld.width / 256) – huggie Oct 21 '13 at 07:55
  • 12
    to stick to Objective C standards, the method's name should be zoomLevel instead of getZoomLevel. – The dude Nov 11 '13 at 11:47
  • 3
    Simplest way is to create a category: https://gist.github.com/d2burke/ad29811b07ae31b378ff (credit to Nikita Galayko @NiKe – d2burke Jul 03 '14 at 15:13
17

You can use span inside the region property of the MKMapView. It is defined like this:

typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta;
} MKCoordinateSpan;

Take a look at the documentation. It is well explained there.

Fran Sevillano
  • 8,103
  • 4
  • 31
  • 45
13

All the previous answers do not take into consideration current map rotation. MKMapView's longitudeDelta differs for non-rotated map and rotated map. Here is a great function for straight map zoom calculation: https://stackoverflow.com/a/15020534/4923516

And here is my improvement in Swift, that takes into consideration map rotation and returns current zoom level:

class MyMapView : MKMapView {

  func getZoom() -> Double {
    // function returns current zoom of the map
    var angleCamera = self.camera.heading
    if angleCamera > 270 {
        angleCamera = 360 - angleCamera
    } else if angleCamera > 90 {
        angleCamera = fabs(angleCamera - 180)
    }
    let angleRad = M_PI * angleCamera / 180 // camera heading in radians
    let width = Double(self.frame.size.width)
    let height = Double(self.frame.size.height)
    let heightOffset : Double = 20 // the offset (status bar height) which is taken by MapKit into consideration to calculate visible area height
    // calculating Longitude span corresponding to normal (non-rotated) width
    let spanStraight = width * self.region.span.longitudeDelta / (width * cos(angleRad) + (height - heightOffset) * sin(angleRad))
    return log2(360 * ((width / 256) / spanStraight)) + 1;
  }

}

You can download sample project in my repo: https://github.com/d-babych/mapkit-wrap

Community
  • 1
  • 1
Dmytro Babych
  • 270
  • 2
  • 7
  • This code helped me, although I omitted the heightOffset concept because I do not think it is applicable to my situation (my MKMapView does not cover the entire screen). – Mark Smith Dec 20 '22 at 16:46
  • How can this be done for SwiftUI? – AnaMM Jul 03 '23 at 15:34
12

The easiest way to get an Integer of the current zoom level, is by using the MapView function: regionDidChangeAnimated. This function recognizes every change in zoom and will give you the basis for the calculation of the zoom factor.

Just insert this function into your MapView class (works for Swift 3.0):

var mapView: MKMapView! = nil

...

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    let zoomWidth = mapView.visibleMapRect.size.width
    let zoomFactor = Int(log2(zoomWidth)) - 9
    print("...REGION DID CHANGE: ZOOM FACTOR \(zoomFactor)")
}

And you will get a zoomFactor value out of it, where 0 is the most near point you can zoom into the map and every higher value is a far far away zoom... :-)

MosTwanTedT
  • 323
  • 3
  • 12
1

If it helps you can also use mapView.camera.altitude to get the current altitude of the currently displayed map region.

This is what helped me when I searched how to get the map zoom level.

razvan
  • 355
  • 4
  • 19