Подтвердить что ты не робот

Проверьте, изменился ли масштаб

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

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

Справка

10x

4b9b3361

Ответ 1

Достаточно просто рассчитать уровень масштабирования. См. Фрагмент ниже. Вы можете получить параметр 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))
    }

}

Ответ 2

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

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

Ответ 3

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

Ответ 4

вы можете прослушивать метод 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 немного изменятся только из-за формы Земли, а не потому, что пользователь увеличил масштаб. должны обнаружить большое изменение в дельтах и ​​игнорировать небольшие изменения.

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

Ответ 5

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

Самый простой способ получить 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 - самая близкая точка, которую вы можете увеличить на карте, и каждое более высокое значение - это далекое расстояние...: -)

Ответ 6

Вероятно, это не тот ответ, который вы хотите услышать, но я не верю, что для этого существует определенный метод делегирования. (В настоящее время, безусловно, нет публичного.)

Таким образом, вам придется использовать метод mapView: regionDidChangeAnimated: вы выделили.

Ответ 7

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

Ответ 8

Увеличить масштаб масштаба в 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
    }
}