Проверьте, изменился ли уровень масштабирования - PullRequest
23 голосов
/ 05 декабря 2010

Я использую MapKit на iPhone.Как узнать, когда пользователь изменяет уровень масштабирования (увеличение / уменьшение карты)?

Я пытался использовать mapView: (MKMapView *) mapView regionDidChangeAnimated: (BOOL) animated; но это называется, даже когда карта только перетаскивается.К сожалению, при перетаскивании карты изменяется и mapView.region.span ...

Справка?

10x

Ответы [ 7 ]

35 голосов
/ 06 декабря 2010

Довольно просто рассчитать уровень масштабирования. Смотрите фрагмент ниже. Вы можете получить параметр 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, так как это скажет вам, изменился ли масштаб вообще.

Я понял это, прочитав отличные сообщения в блоге Троя Бранта на эту тему:

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

}
11 голосов
/ 27 августа 2011

Я нашел это очень полезным и разработал следующий код на основе этих ответов.

- (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 голосов
/ 18 марта 2012

У меня есть следующая категория 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];
}
1 голос
/ 15 ноября 2016

Гораздо более простой ответ:

Самый простой способ получить целое число текущего уровня масштабирования - использовать функцию 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 голос
/ 05 декабря 2010

вы можете прослушать метод 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");
}

Это должно определить, изменился ли масштаб карты.

однако вам следует избегать изменения масштаба, потому что Земля искривлена ​​:( Если прокрутить карту, значения latitudeDelta и longitudeDelta будут немного меняться только из-за формы Земли, а не из-за увеличения масштаба пользователя. должны обнаруживать большие изменения в дельтах и ​​игнорировать небольшие изменения.

Надеюсь, это поможет.

0 голосов
/ 07 сентября 2016

Подсчет масштаба увеличения в 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
    }
}
0 голосов
/ 05 декабря 2010

Вы можете сохранить дельту широты, затем при вызове regionDidChangeAnimated: проверьте, не отличается ли новая дельта широты.Я думаю, что дельта широты остается постоянной, пока карта не увеличена.

...