iphone - operador - no se pudo iniciar sesion ocurrio un problema al conectar con el servidor
Compruebe si el nivel de zoom ha cambiado (8)
Estoy usando MapKit en iPhone. ¿Cómo puedo saber cuándo el usuario cambia el nivel de zoom (acercar / alejar el mapa)?
He intentado usar mapView: (MKMapView *) mapView regionDidChangeAnimated: (BOOL) animated; pero eso se llama incluso cuando el mapa solo se arrastra. Desafortunadamente, cuando el mapa se arrastra, mapView.region.span también cambia ...
¿Ayuda?
10x
Encontré esto muy útil y desarrollé el siguiente código basado en estas respuestas.
- (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];
}
}
}
Podría guardar un delta de latitud, luego, cuando se regionDidChangeAnimated:
verifique si el nuevo delta de latitud es diferente. Creo que la latitud delta se mantiene constante mientras el mapa no se amplíe.
Probablemente no sea la respuesta que desea escuchar, pero no creo que haya un método de delegado específico para esto. (Ciertamente no hay actualmente una pública).
Como tal, tendrás que usar el método mapView: regionDidChangeAnimated: que has resaltado.
Tengo la siguiente categoría MKMapView en la que incluyo un método para obtener rápidamente el nivel de zoom actual para el mapa:
@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
Para obtener el nivel de zoom, puede llamar a lo siguiente en sus delegados y determinar si el nivel de zoom ha cambiado:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
NSUInteger zoomLevel = [mapView zoomLevel];
}
puedes escuchar el mapView:regionDidChangeAnimated:
Sin embargo, esto no le dice si el nivel de zoom cambió, solo si el mapa estaba animado.
También deberá escuchar la propiedad de region
de la vista de mapa. Este contiene los valores latitudeDelta y longitudeDelta que se pueden usar para calcular si el nivel de zoom ha cambiado.
es decir, en el archivo .h
@class MyMapViewController {
...
MKCoordinateRegion mapRegion;
}
@end
y en tu archivo .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");
}
Esto debería detectar si el zoom del mapa ha cambiado.
sin embargo, debe cambiar para cambiar el zoom porque la Tierra está curvada :( Si el mapa se desplaza, la latitudDelta y la longitudDelta cambiarán ligeramente solo por la forma de la Tierra, no porque el usuario haya hecho zoom. Es posible que tenga que detectar Un gran cambio en los deltas e ignoran ligeros cambios.
Espero que ayude.
Respuesta mucho más simple:
La forma más fácil de obtener un entero del nivel de zoom actual es mediante el uso de la función MapView: regionDidChangeAnimated. Esta función reconoce cada cambio en el zoom y le dará la base para el cálculo del factor de zoom.
Simplemente inserte esta función en su clase MapView ( funciona para 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)")
}
Y obtendrás un valor zoomFactor, donde 0 es el punto más cercano al que puedes hacer zoom en el mapa y cada valor más alto está muy lejos ... :-)
Contar escala de zoom en MKMapView - solución Swift
Creé la siguiente extensión para MKMapView, para que pueda obtener una escala de zoom en el mapa. La solución es similar a la presentada anteriormente pero en Swift.
También hay una función adicional scaleWithPrecision(_:Int64)
para redondear esa escala que permite filtrar f.ex. pequeños cambios de zoom en 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
}
}
Es bastante simple calcular el nivel de zoom. Vea el fragmento a continuación. Puede obtener el parámetro mRect de la propiedad visibleMapRect
en su instancia de 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;
}
Probablemente podría detenerse en el paso para calcular el zoomScale
ya que le dirá si el zoom ha cambiado en absoluto.
Me di cuenta de esto leyendo las excelentes publicaciones del blog de Troy Brants sobre el tema:
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))
}
}