Skip to content

Instantly share code, notes, and snippets.

@appsandwich
Created January 10, 2014 15:04
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save appsandwich/8355891 to your computer and use it in GitHub Desktop.
Save appsandwich/8355891 to your computer and use it in GitHub Desktop.
Get & set the zoom level of a MKMapView
@interface MKMapView (Extensions)
-(double)as_zoomLevel;
-(void)as_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated;
@end
static double mercadorRadius = 85445659.44705395;
static double mercadorOffset = 268435456;
@implementation MKMapView (Extensions)
-(double)as_zoomLevel {
// Derived from http://stackoverflow.com/questions/7594827/how-to-find-current-zoom-level-of-mkmapview
static double maxGoogleLevels = -1.0;
if (maxGoogleLevels < 0.0)
maxGoogleLevels = log2(MKMapSizeWorld.width / 256.0);
CLLocationDegrees longitudeDelta = self.region.span.longitudeDelta;
CGFloat mapWidthInPixels = self.bounds.size.width;
double zoomScale = longitudeDelta * mercadorRadius * M_PI / (180.0 * mapWidthInPixels);
double zoomer = maxGoogleLevels - log2( zoomScale );
if ( zoomer < 0 ) zoomer = 0;
return zoomer;
}
// http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/
#pragma mark -
#pragma mark Map conversion methods
-(double)as_longitudeToPixelSpaceX:(double)longitude {
return round(mercadorOffset + mercadorRadius * longitude * M_PI / 180.0);
}
-(double)as_latitudeToPixelSpaceY:(double)latitude {
return round(mercadorOffset - mercadorRadius * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
}
-(double)as_pixelSpaceXToLongitude:(double)pixelX {
return ((round(pixelX) - mercadorOffset) / mercadorRadius) * 180.0 / M_PI;
}
-(double)as_pixelSpaceYToLatitude:(double)pixelY {
return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - mercadorOffset) / mercadorRadius))) * 180.0 / M_PI;
}
#pragma mark -
#pragma mark Helper methods
-(MKCoordinateSpan)as_coordinateSpanWithMapView:(MKMapView *)mapView centerCoordinate:(CLLocationCoordinate2D)centerCoordinate andZoomLevel:(NSUInteger)zoomLevel {
// convert center coordiate to pixel space
double centerPixelX = [self as_longitudeToPixelSpaceX:centerCoordinate.longitude];
double centerPixelY = [self as_latitudeToPixelSpaceY:centerCoordinate.latitude];
// determine the scale value from the zoom level
NSInteger zoomExponent = 20 - zoomLevel;
double zoomScale = pow(2, zoomExponent);
// scale the map’s size in pixel space
CGSize mapSizeInPixels = mapView.bounds.size;
double scaledMapWidth = mapSizeInPixels.width * zoomScale;
double scaledMapHeight = mapSizeInPixels.height * zoomScale;
// figure out the position of the top-left pixel
double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
// find delta between left and right longitudes
CLLocationDegrees minLng = [self as_pixelSpaceXToLongitude:topLeftPixelX];
CLLocationDegrees maxLng = [self as_pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
CLLocationDegrees longitudeDelta = maxLng - minLng;
// find delta between top and bottom latitudes
CLLocationDegrees minLat = [self as_pixelSpaceYToLatitude:topLeftPixelY];
CLLocationDegrees maxLat = [self as_pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
// create and return the lat/lng span
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return span;
}
-(void)as_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated {
// clamp large numbers to 28
zoomLevel = MIN(zoomLevel, 28);
// use the zoom level to compute the region
MKCoordinateSpan span = [self as_coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
// set the region like normal
[self setRegion:region animated:animated];}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment