web-dev-qa-db-ja.com

ズームレベルが変更されたかどうかを確認します

IPhoneでMapKitを使用しています。ユーザーがズームレベルを変更したとき(マップをズームイン/ズームアウト)を知るにはどうすればよいですか?

mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;を使用しようとしましたが、マップがドラッグされただけの場合でも呼び出されます。残念ながら、マップをドラッグすると、mapView.region.spanも変更されます...

助けて?

10倍

23
Rizon

ズームレベルの計算は非常に簡単です。以下のスニペットを参照してください。 mRectパラメータは、visibleMapRectインスタンスのMKMapViewプロパティから取得できます。

+ (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を計算するステップで停止することができます。

このトピックに関するTroyBrantsの優れたブログ投稿を読んで、このことを理解しました。

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

}
37
Aaron

私はこれが非常に役立つと感じ、これらの回答に基づいて次のコードを開発しました。

- (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];
    }
  }
}
11
Brian Oldfield

次の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];
}
2
u10int

はるかに簡単な答え:

現在のズームレベルの整数を取得する最も簡単な方法は、MapView関数regionDidChangeAnimatedを使用することです。この関数は、ズームのすべての変更を認識し、ズーム率の計算の基礎を提供します。

この関数をMapViewクラスに挿入するだけです(Swift 3.で動作します):

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
MosTwanTedT

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");
}

これにより、マップのズームが変更されたかどうかが検出されます。

ただし、地球は湾曲しているため、ズームの変更に注意する必要があります:(マップをスクロールすると、ユーザーがズームしたためではなく、地球の形状だけで緯度デルタと経度デルタがわずかに変化します。検出する必要がある場合があります。デルタの大きな変化とわずかな変化を無視します。

お役に立てば幸いです。

1
deanWombourne

MKMapViewのズームスケールをカウント-Swiftソリューション

MKMapViewの次の拡張機能を作成したので、地図上でズームのスケールを取得できます。解決策は上記と同様ですが、Swiftを使用します。

F.exを除外できるようにするスケールを丸めるための追加の関数scaleWithPrecision(_:Int64)もあります。 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
    }
}
0
lukszar