1 #import <MAMapKit/MAMapKit.h>
2
3 @interface MAMapView (ZoomLevel)
4 - (NSUInteger)getZoomLevel;
5
6 - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
7 zoomLevel:(NSUInteger)zoomLevel
8 animated:(BOOL)animated;
9
10 - (void)zoomToFitMapAnnotations;
11 @end
1 //
2 // MAMapView+ZoomLevel.m
3 // Yjf
4 //
5 // Created by iMac on 14/12/2.
6 // Copyright (c) 2014年 POTech. All rights reserved.
7 //
8
9 #import "MAMapView+ZoomLevel.h"
10
11 #define MERCATOR_OFFSET 268435456
12 #define MERCATOR_RADIUS 85445659.44705395
13
14 @implementation MAMapView (ZoomLevel)
15
16 #pragma mark - Map conversion methods
17
18 - (double)longitudeToPixelSpaceX:(double)longitude
19 {
20 return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
21 }
22
23 - (double)latitudeToPixelSpaceY:(double)latitude
24 {
25 return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
26 }
27
28 - (double)pixelSpaceXToLongitude:(double)pixelX
29 {
30 return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
31 }
32
33 - (double)pixelSpaceYToLatitude:(double)pixelY
34 {
35 return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
36 }
37
38 #pragma mark - Helper methods
39
40 - (MACoordinateSpan)coordinateSpanWithMapView:(MAMapView *)mapView
41 centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
42 andZoomLevel:(NSUInteger)zoomLevel
43 {
44 // convert center coordiate to pixel space
45 double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
46 double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
47
48 // determine the scale value from the zoom level
49 NSInteger zoomExponent = 20 - zoomLevel;
50 double zoomScale = pow(2, zoomExponent);
51
52 // scale the map’s size in pixel space
53 CGSize mapSizeInPixels = mapView.bounds.size;
54 double scaledMapWidth = mapSizeInPixels.width * zoomScale;
55 double scaledMapHeight = mapSizeInPixels.height * zoomScale;
56
57 // figure out the position of the top-left pixel
58 double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
59 double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
60
61 // find delta between left and right longitudes
62 CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
63 CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
64 CLLocationDegrees longitudeDelta = maxLng - minLng;
65
66 // find delta between top and bottom latitudes
67 CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
68 CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
69 CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
70
71 // create and return the lat/lng span
72 MACoordinateSpan span = MACoordinateSpanMake(latitudeDelta, longitudeDelta);
73 return span;
74 }
75
76 #pragma mark - Public methods
77
78 - (NSUInteger)getZoomLevel
79 {
80 return 21-round(log2(self.region.span.longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * self.bounds.size.width)));
81 }
82
83 - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
84 zoomLevel:(NSUInteger)zoomLevel
85 animated:(BOOL)animated
86 {
87 // clamp large numbers to 28
88 zoomLevel = MIN(zoomLevel, 28);
89
90 // use the zoom level to compute the region
91 MACoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
92 MACoordinateRegion region = MACoordinateRegionMake(centerCoordinate, span);
93
94 // set the region like normal
95 [self setRegion:region animated:animated];
96 }
97
98 - (void)zoomToFitMapAnnotations
99 {
100 if ([self.annotations count] == 0) return;
101
102 CLLocationCoordinate2D topLeftCoord;
103 topLeftCoord.latitude = -90;
104 topLeftCoord.longitude = 180;
105
106 CLLocationCoordinate2D bottomRightCoord;
107 bottomRightCoord.latitude = 90;
108 bottomRightCoord.longitude = -180;
109
110 for(id<MAAnnotation> annotation in self.annotations) {
111 if ([annotation isKindOfClass:[MAUserLocation class]]) {
112 continue;
113 }
114 topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
115 topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
116 bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
117 bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
118 }
119
120 MACoordinateRegion region;
121 region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
122 region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
123 region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.2;
124 region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.2;
125
126 region = [self regionThatFits:region];
127 [self setRegion:region animated:YES];
128 }
129
130 @end