检查缩放级别是否已更改

时间:2010-12-05 15:12:24

标签: iphone objective-c iphone-sdk-3.0 mapkit mkmapview

我在iPhone上使用MapKit。 如何知道用户何时更改缩放级别(放大\ out the map)?

我尝试使用 mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)动画; 但即使只拖动地图也会调用它。 不幸的是,当拖动地图时,mapView.region.span也会发生变化......

帮助?

10倍

7 个答案:

答案 0 :(得分:35)

计算缩放级别非常简单。请参阅下面的代码段。您可以从visibleMapRect实例的MKMapView属性中获取mRect参数。

+ (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的步骤,因为它会告诉您缩放是否完全改变了。

我从阅读Troy Brants关于这个话题的优秀博客文章中找到了这些东西:

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

Swift 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))
    }

}

答案 1 :(得分: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 :(得分: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];
}

答案 3 :(得分:1)

您可以听取mapView:regionDidChangeAnimated:方法。但是,这并不会告诉您缩放级别是否已更改,只是地图已设置动画。

您还需要侦听地图视图的region属性。它包含latitudeDelta和longitudeDelta值,可用于计算缩放级别是否已更改。

即。在.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");
}

这应检测地图缩放是否已更改。

然而,你应该为变焦而改变因为地球是弯曲的:(如果滚动地图,纬度Delta和longitudeDelta会因为地球的形状而稍微改变,而不是因为用户已经放大了。你可能会必须检测增量的大变化并忽略轻微的变化。

希望有所帮助。

答案 4 :(得分:1)

更简单的答案:

获取当前缩放级别的Integer的最简单方法是使用MapView函数:regionDidChangeAnimated。此功能可识别缩放的每个变化,并为您提供缩放系数计算的基础。

只需将此函数插入​​MapView类(适用于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)")
}

你会得到一个zoomFactor值,其中0是你可以放大到地图的最近点,每个更高的值都是遥远的缩放......: - )

答案 5 :(得分:0)

计算MKMapView中的缩放比例 - Swift解决方案

我为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
    }
}

答案 6 :(得分:-1)

您可以保存纬度增量,然后在调用regionDidChangeAnimated:时,检查新的纬度增量是否不同。我认为只要地图没有缩放,纬度增量就会保持不变。