how to find current zoom level of MKMapView?
Asked Answered
F

5

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?

Farah answered 29/9, 2011 at 8:57 Comment(1)
Just check answer from <https://mcmap.net/q/237440/-mkmapview-zoom-and-region>Corporate
N
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.

Nerin answered 29/9, 2011 at 9:9 Comment(0)
J
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
Jespersen answered 14/2, 2012 at 10:53 Comment(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)Paranymph
That is log2(MKMapSizeWorld.width / 256)Paranymph
to stick to Objective C standards, the method's name should be zoomLevel instead of getZoomLevel.Hyperdulia
Simplest way is to create a category: gist.github.com/d2burke/ad29811b07ae31b378ff (credit to Nikita Galayko @JespersenWickman
N
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.

Nerin answered 29/9, 2011 at 9:9 Comment(0)
V
14

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://mcmap.net/q/173522/-setting-the-zoom-level-for-a-mkmapview

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

Ventricular answered 15/2, 2016 at 12:36 Comment(2)
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).Amazonas
How can this be done for SwiftUI?Disband
S
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... :-)

Sex answered 15/11, 2016 at 17:36 Comment(3)
Why - 9 at the zoomFactor?Zeus
The 9 is not necessary, it is just for the case if you want to end-up the maximum zoom factor to 0.... without the 9, in my case it will end with 9.Sex
That would make the -9 necessary because this is how the standard zoom level works.Teressaterete
T
3

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.


Latest syntax:

let zoomage = mapView.camera.centerCoordinateDistance
Touristy answered 6/5, 2019 at 11:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.