如何查找MKMapView的当前缩放级别?

30

我想知道在iPhone编程中,如何获取MKMapView的当前缩放级别? 实际上,我有一个应用程序,它需要几个参数(从MKMapView中心到角落的半径),并返回该区域内的商店详细信息。当我在MKMapView上时,半径很大,并且在半径较小时更改。因此,我想知道当前MKMapView可见区域的缩放级别,并根据此设置我的Web服务。如何获取当前MKMapView的缩放级别?


1
只需检查来自以下网址的答案: https://dev59.com/cnM_5IYBdhLWcg3w6X5e - Minakshi
5个回答

52

我为此创建了一个非常简单的帮助子类:

#define MERCATOR_RADIUS 85445659.44705395
#define MAX_GOOGLE_LEVELS 20

@interface MKMapView (ZoomLevel)
- (double)getZoomLevel;
@end

@implementation MKMapView (ZoomLevel)

- (double)getZoomLevel
{
    CLLocationDegrees longitudeDelta = self.region.span.longitudeDelta;
    CGFloat mapWidthInPixels = self.bounds.size.width;
    double zoomScale = longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapWidthInPixels);
    double zoomer = MAX_GOOGLE_LEVELS - log2( zoomScale );
    if ( zoomer < 0 ) zoomer = 0;
//  zoomer = round(zoomer);
    return zoomer;
}

@end

我认为可以从 MKMapSizeWorld.width / 256 获取 MAX_GOOGLE_LEVELS,并取其 log2 值,其中 256 是像素(或者可能是点)的瓦片宽度或高度。 - huggie
这是 log2(MKMapSizeWorld.width / 256)。 - huggie
12
为了遵循 Objective-C 的标准,该方法的名称应该是 zoomLevel 而不是 getZoomLevel。 - The dude
3
最简单的方法是创建一个类别:https://gist.github.com/d2burke/ad29811b07ae31b378ff(由Nikita Galayko @NiKe贡献) - d2burke

17

您可以在 MKMapViewregion 属性内使用 span。它的定义如下:

typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta;
} MKCoordinateSpan;

请查看文档,那里讲得很清楚。


13

所有之前的答案都没有考虑当前地图旋转。MKMapView在非旋转和旋转状态下的longitudeDelta不同。以下是一个非常好用的函数,用于计算直接地图缩放:https://dev59.com/d2855IYBdhLWcg3wsWv3#15020534

这里是我在Swift中对其进行改进后,考虑了地图旋转并返回当前缩放级别的版本:

class MyMapView : MKMapView {

  func getZoom() -> Double {
    // function returns current zoom of the map
    var angleCamera = self.camera.heading
    if angleCamera > 270 {
        angleCamera = 360 - angleCamera
    } else if angleCamera > 90 {
        angleCamera = fabs(angleCamera - 180)
    }
    let angleRad = M_PI * angleCamera / 180 // camera heading in radians
    let width = Double(self.frame.size.width)
    let height = Double(self.frame.size.height)
    let heightOffset : Double = 20 // the offset (status bar height) which is taken by MapKit into consideration to calculate visible area height
    // calculating Longitude span corresponding to normal (non-rotated) width
    let spanStraight = width * self.region.span.longitudeDelta / (width * cos(angleRad) + (height - heightOffset) * sin(angleRad))
    return log2(360 * ((width / 256) / spanStraight)) + 1;
  }

}

您可以在我的存储库中下载示例项目:https://github.com/d-babych/mapkit-wrap


这段代码对我很有帮助,尽管我省略了heightOffset的概念,因为我认为它不适用于我的情况(我的MKMapView并没有覆盖整个屏幕)。 - Mark Smith
如何在SwiftUI中实现这个? - AnaMM

12

获取当前缩放级别的最简单方法是使用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是您可以缩放到地图上的最近点,每个更高的值都是一个遥远的缩放... :-)


1
为什么缩放因子是9? - miff
9不是必需的,只是为了在最大缩放因子达到0时使用... 在没有9的情况下,在我的情况下它将以9结束。 - MosTwanTedT
这将使得-9成为必需,因为这是标准缩放级别的工作方式。 - Richard Witherspoon

1
如果需要,您还可以使用 mapView.camera.altitude 来获取当前显示的地图区域的海拔高度。当我搜索如何获取地图缩放级别时,这就是帮助我的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接