2010-12-05 230 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表示最近点,你可以放大地图和每一个更高的值是一个遥远的距离放大... :-)