2010-12-05 229 views
22

我在iPhone上使用MapKit。 如何知道用戶何時更改縮放級別(放大地圖)?檢查縮放級別是否改變

我試過用mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;但即使僅在拖動地圖時纔會調用。 不幸的是,當地圖拖動時,mapView.region.span也會發生變化...

幫助?

10X

回答

34

這是很簡單的計算縮放級別。請參見下面的代碼片段,您可以從該mRect參數visibleMapRectMKMapView

+ (NSUInteger)zoomLevelForMapRect:(MKMapRect)mRect withMapViewSizeInPixels:(CGSize)viewSizeInPixels 
{ 
    NSUInteger zoomLevel = MAXIMUM_ZOOM; // MAXIMUM_ZOOM is 20 with MapKit 
    MKZoomScale zoomScale = mRect.size.width/viewSizeInPixels.width; //MKZoomScale is just a CGFloat typedef 
    double zoomExponent = log2(zoomScale); 
    zoomLevel = (NSUInteger)(MAXIMUM_ZOOM - ceil(zoomExponent)); 
    return zoomLevel; 
} 

您可以在計算zoomScale的步驟中停止,因爲它會告訴您縮放是否已經改變。

我想通了這東西了從主題閱讀特洛伊Brants優秀的博客文章:

http://troybrant.net/blog/2010/01/mkmapview-and-zoom-levels-a-visual-guide/

斯威夫特3

extension MKMapView { 

    var zoomLevel: Int { 
     let maxZoom: Double = 20 
     let zoomScale = self.visibleMapRect.size.width/Double(self.frame.size.width) 
     let zoomExponent = log2(zoomScale) 
     return Int(maxZoom - ceil(zoomExponent)) 
    } 

} 
0

可能不是你想要聽到的答案,但我不相信有一個特定的委託方法這一點。 (目前肯定沒有公開的。)

因此,您必須使用您已突出顯示的mapView:regionDidChangeAnimated:方法。

0

您可以保存緯度增量,然後當調用regionDidChangeAnimated:時,檢查新緯度增量是否不同。我認爲只要地圖沒有放大,緯度三角洲就會保持不變。

+0

好吧,你錯了。 跨度值在您拖動地圖時發生變化。 – Rizon 2010-12-06 00:31:46

1

你可以聽mapView:regionDidChangeAnimated:方法。但是,這並不會告訴您縮放級別是否發生了變化,就像地圖是動畫一樣。

您還需要聽地圖視圖的region屬性。這包含可用於計算縮放級別是否已更改的緯度Delta和經度Delta值。

在.h文件

@class MyMapViewController { 
    ... 
    MKCoordinateRegion mapRegion; 
    } 
@end 

,並在您.m文件

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { 
    mapRegion = mapView.region; 
} 

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { 
    newRegion = mapView.region; 

    if (mapRegion.span.latitudeDelta != newRegion.span.latitudeDelta || 
     mapRegion.span.longitudeDelta != newRegion.span.longitudeDelta) 
     NSLog(@"The zoom has changed"); 
} 

如果地圖縮放更改時,這應檢測

即。

但是,由於地球是彎曲的,你應該研究變焦變化:(如果地圖是滾動的緯度,則經度和緯度只會因爲地球的形狀而稍微變化,而不是因爲用戶放大。可能需要檢測三角洲大的變化,而忽略細微的變化。

希望有所幫助。

+0

比我的答案要完整得多。我認爲經度三角洲在你走向兩極時會發生變化,但是無論你走到哪裏,緯度三角洲都會保持不變。可能需要一些測試來檢查它是否足夠使用。 – 2010-12-05 15:53:01

+0

我永遠不會記得哪些變化,哪些不會,所以我剛剛在我的回答中都測試過了:)我想你可以測試一下,看看他們是否改變它必須是一個用戶縮放,如果只有一個改變它很多是一個滾動? – deanWombourne 2010-12-05 16:19:34

+0

夥計們我希望你能在發佈之前對你的「解決方案」進行一些小小的檢查。 非你的想法工作。跨度三角洲確實發生了變化 - 而且變化很大。 – Rizon 2010-12-06 00:36:52

11

我發現這非常有幫助,並制定了以下代碼基於這些答案。

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated 
{ 
    mapRegion = self.mapView.region; 
} 


-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ 

MKCoordinateRegion newRegion = self.mapView.region; 

NSInteger zFactor; 
if ((mapRegion.span.latitudeDelta/newRegion.span.latitudeDelta) > 1.5){ 
    NSLog(@"Zoom in changed"); 
    zFactor = 20; 
    CustomPlacemark *aO; 
    MKAnnotationView *aV; 
    for (aO in self.mapView.annotations) { 
     aV = [[self mapView] viewForAnnotation:aO]; 
     aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y, aV.frame.size.width+zFactor, aV.frame.size.height+zFactor); 
     [[[self mapView] viewForAnnotation:aO] setFrame:aV.frame]; 
    } 
} 
if ((mapRegion.span.latitudeDelta/newRegion.span.latitudeDelta) < 0.75){ 
    NSLog(@"Zoom out"); 
    zFactor = -20; 
    CustomPlacemark *aO; 
    MKAnnotationView *aV; 
    for (aO in self.mapView.annotations) { 
     aV = [[self mapView] viewForAnnotation:aO]; 
     aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y, aV.frame.size.width+zFactor, aV.frame.size.height+zFactor); 
     [[[self mapView] viewForAnnotation:aO] setFrame:aV.frame]; 
    } 
    } 
} 
2

,我有以下的MKMapView類中,我包括快速獲取當前縮放級別地圖的方法:

@implementation MKMapView (ZoomLevel) 

- (NSUInteger) zoomLevel { 
    MKCoordinateRegion region = self.region; 

    double centerPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude]; 
    double topLeftPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta/2]; 

    double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2; 
    CGSize mapSizeInPixels = self.bounds.size; 
    double zoomScale = scaledMapWidth/mapSizeInPixels.width; 
    double zoomExponent = log(zoomScale)/log(2); 
    double zoomLevel = 21 - zoomExponent; 

    return zoomLevel; 
} 

@end 

爲了得到縮放級別,您可以撥打以下的代表和確定縮放級別已經改變:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { 
    NSUInteger zoomLevel = [mapView zoomLevel]; 
} 
0

計數放大規模的MKMapView - 迅速解決

我爲MKMapView創建了以下擴展,因此您可以在地圖上獲得縮放比例。該解決方案與上面介紹的類似,但在Swift中。

還有一個額外的功能scaleWithPrecision(_:Int64)四捨五入的規模,允許過濾掉f.ex。在MapView的

extension MKMapView { 

    var scale: Double { 

     return self.scaleWithPrecision(1) 
    } 

    func scaleWithPrecision(precision: Int64) -> Double { 

     let mapBoundsWidth = Double(self.bounds.size.width) 
     let mapRectWidth:Double = self.visibleMapRect.size.width 

     let scale: Double = round(Double(precision)*mapBoundsWidth/mapRectWidth)/Double(precision) 

     return scale 
    } 
} 
1

小變焦的變化更簡單的答案:

來獲得當前縮放級別的整數最簡單的方法,就是使用的MapView功能:regionDidChangeAnimated。此功能可識別變焦中的每個變化,併爲您提供變焦係數計算的基礎。

只需插入此功能到您的MapView類(作品雨燕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)") 
} 

,你會得到一個zoomFactor值出來,其中0表示最近點,你可以放大地圖和每一個更高的值是一個遙遠的距離放大... :-)