Проверьте, изменился ли масштаб
Я использую MapKit на iPhone.
Как узнать, когда пользователь меняет уровень масштабирования (масштабирование\на карте)?
Я попытался использовать mapView: (MKMapView *) mapView regionDidChangeAnimated: (BOOL) анимированный;, но вызываемый, даже когда карта только таскается.
К сожалению, при перетаскивании карты также изменяется mapView.region.span...
Справка
10x
Ответы
Ответ 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
}
}