Cambiar el tamaño de la image MKAnnotationView Cuando el zoom se acerca y se aleja?

Lo que tengo

Tengo alnetworkingedor de 150 MKAnnotationViews en un map. Cada MKAnnotationView tiene una image que reemplaza al pin pnetworkingeterminado.

Qué está pasando ahora

Cuando el map aumenta, las MKAnnotationViews se hacen más pequeñas y lo contrario cuando se aleja.

Lo que deseo sucedió

Bueno, quiero que sea al revés. Dado que cuando el map es pequeño, deseo que MKAnnotationViews sea más pequeño para que el usuario pueda verlos todos, y cuando acerque los zoom, desearía que sean más grandes.

¿Qué código tengo hasta ahora?

Sé cómo get el cambio de zoom, y sé que puedo get el "pMapView.region.span.latitudeDelta" como reference para la cantidad de zoom. y sé que puedo cambiar el annotationView.frame.

-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated{ NSLog(@"mapView.region.span.latitudeDelta = %f",pMapView.region.span.latitudeDelta); for (id <MKAnnotation> annotation in pMapView.annotations) { MKAnnotationView *annotationView = [pMapView viewForAnnotation: annotation]; } } 

¿Alguien me puede ayudar con eso? Gracias shani

De hecho, en el MKMapView pnetworkingeterminado, la anotación (por ejemplo, el pin o la image) y la llamada (por ejemplo, burbuja) siguen siendo del mismo tamaño a medida que aumenta o disminuye el zoom. No escalan. Pero consigo su punto: en relación con el map, parecen estar creciendo a medida que el map se aleja y se networkinguce al acercarse el map.

Entonces, hay dos soluciones a su problema y funcionan de manera ligeramente diferente:

  1. Implementar -(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated desde la reference del protocolo MKMapViewDelegate, que ya has hecho.
  2. Adjunte un UIPinchGestureRecognizer al object MKMapView y luego implemente la acción.

Opción n. ° 1: mapView:regionDidChangeAnimated: se llamará a un desplazamiento o un evento de zoom, básicamente en cualquier momento en que cambie la región del map como su nombre lo indica. Esto da como resultado un cambio de icons ligeramente less suave, ya que los events del map se disparan con less frecuencia.

Mis preferences son para la opción n. ° 2: adjunte un UIPinchGestureRecognizer al object MKMapView y luego implemente la acción. Los events con gestos pellizcos se activan con bastante rapidez, por lo que obtienes un cambio de tamaño suave del ícono. Y solo disparan para un evento de pellizco reconocido, por lo que no dispararán durante un evento de desplazamiento.

Los methods de acción invocados deben cumplir con una de las siguientes firmas:

- (void)handleGesture;
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;

Debe tener cuidado de no anular el comportamiento del zoom pnetworkingeterminado de los maps. Consulte esta publicación: "UIMapView: UIPinchGestureRecognizer not called" para get más información. La respuesta corta es que debe implementar shouldRecognizeSimultaneouslyWithGestureRecognizer: y devuelva YES.

Todo lo dicho aquí es un código de ejemplo:

 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; self.mapView.mapType = MKMapTypeStandard; // also MKMapTypeSatellite or MKMapTypeHybrid // Add a pinch gesture recognizer UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; pinchRecognizer.delegate = self; [self.mapView addGestureRecognizer:pinchRecognizer]; [pinchRecognizer release]; } #pragma mark - #pragma mark UIPinchGestureRecognizer - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchRecognizer { if (pinchRecognizer.state != UIGestureRecognizerStateChanged) { return; } MKMapView *aMapView = (MKMapView *)pinchRecognizer.view; for (id <MKAnnotation>annotation in aMapView.annotations) { // if it's the user location, just return nil. if ([annotation isKindOfClass:[MKUserLocation class]]) return; // handle our custom annotations // if ([annotation isKindOfClass:[MKPointAnnotation class]]) { // try to retrieve an existing pin view first MKAnnotationView *pinView = [aMapView viewForAnnotation:annotation]; //Format the pin view [self formatAnnotationView:pinView forMapView:aMapView]; } } } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } 

Entonces, en este punto, nuevamente tiene varias opciones para cambiar el tamaño de la anotación. Las dos muestras de código siguientes se basan en el código de Troy Brant para get el nivel de zoom de un MKMapView .

  1. Cambia el tamaño de TANTO la image de la anotación como la llamada usando una transformada. Personalmente, creo que la transformación resulta en un cambio de tamaño más limpio. Pero en la mayoría de los casos, no se requiere networkingimensionar la llamada.
  2. Cambia el tamaño solo de la image de la anotación. Utilizo el tamaño de UIImage de Trevor Harmon de la manera correcta, pero de nuevo mi opinión es que no es tan claro como cambiar el tamaño.

Aquí hay un código de ejemplo más:

 - (void)formatAnnotationView:(MKAnnotationView *)pinView forMapView:(MKMapView *)aMapView { if (pinView) { double zoomLevel = [aMapView zoomLevel]; double scale = -1 * sqrt((double)(1 - pow((zoomLevel/20.0), 2.0))) + 1.1; // This is a circular scale function where at zoom level 0 scale is 0.1 and at zoom level 20 scale is 1.1 // Option #1 pinView.transform = CGAffineTransformMakeScale(scale, scale); // Option #2 UIImage *pinImage = [UIImage imageNamed:@"YOUR_IMAGE_NAME_HERE"]; pinView.image = [pinImage resizedImage:CGSizeMake(pinImage.size.width * scale, pinImage.size.height * scale) interpolationQuality:kCGInterpolationHigh]; } } 

Si esto funciona, no olvides marcarlo como la respuesta.

Perdón por mi mal inglés … pero solo quiero ayudar a alguien.

Muchas gracias, Funktional. Su respuesta es genial … funciona perfectamente en iOS5. Pero esto se invalida en iOS6, y parece que no hay solución para resolver este problema por ahora.

Pero finalmente, lo solucioné de una manera estúpida / estática y funciona bien en ambos iOS. No voy a explicar demasiado. Esto es lo que he hecho en mi proyecto.

  1. La image para la mkannotation se llama pin.png (el tamaño es 20×20)

  2. Creé cinco imágenes más con diferentes tamaños para diferentes niveles de zoom (18×18, 16×16, 14×14, 12×12, 10×10) y se llaman pin-5.png, pin-4.png, pin-3.png, pin-2.png , pin-1.png.

  3. Eliminé todo el código sobre el cálculo de la escala en formatAnnotationView y agregué esta línea

     NSString* imageName = [NSString stringWithFormat:@"%@%@.png", [imageName substringToIndex:[imageName length]-4 ], [self getImageLevel]]; 
  4. Además, cambia esto de

    UIImage * pinImage = [UIImage imageNamed: @ "YOUR_IMAGE_NAME_HERE"];

    a

    UIImage * pinImage = [[UIImage alloc] initWithContentsOfFile: imageName];

  5. agrega esta function

     -(NSString *)getImageLevel{ NSString* output; double zoomLevel = [self getZoomLevel:_mapview]; if(zoomLevel >= 19.0) output = @""; else if(zoomLevel < 19.0 && zoomLevel >= 18.0) output = @"-5"; else if(zoomLevel < 18.0 && zoomLevel >= 17.0) output = @"-4"; else if(zoomLevel < 17.0 && zoomLevel >= 16.0) output = @"-3"; else if(zoomLevel < 16.0 && zoomLevel >= 15.0) output = @"-2"; else output = @"-1"; return output;} 

Perdón por la mala encoding y el inglés nuevamente.

Un método alternativo sería networkingimensionar la propiedad de image de vista de anotación. Un ejemplo se muestra en esta publicación.

En Swift 3, esto funcionó para mí. Mi image fue 100% en el nivel 19, por lo que 1/19 me da 0.5263158, que es mi escala lineal:

 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { if annotation is MKUserLocation { return nil } let mkView = MKAnnotationView(annotation: annotation, reuseIdentifier: "mkView") mkView.image = UIImage(named: "Foo") formatAnnotation(pinView: mkView, forMapView: mapView) return mkView; } func formatAnnotation(pinView: MKAnnotationView, forMapView: MKMapView) { let zoomLevel = forMapView.getZoomLevel() let scale = 0.05263158 * zoomLevel //Modify to whatever scale you need. pinView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale)) } 

La respuesta de @ Funktional en Swift 3:

 class MapViewController: UIViewController: UIGestureRecognizerDelegate { @IBOutlet weak var mapView: MKMapView! override func viewDidLoad() { super.viewDidLoad() // You can also add this gesture recognizer and set the delegate via storyboard let pinchGR = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture)) pinchGR.delegate = self self.mapView.addGestureRecognizer(pinchGR) } // link as @IBAction when added via storyboard func handlePinchGesture(_ sender: UIPinchGestureRecognizer) { if sender.state == .ended { for annotation in mapView.annotations { if annotation is MKUserLocation { continue } guard let annotationView = self.mapView.view(for: annotation) else { continue } let scale = -1 * sqrt(1 - pow(mapView.zoomLevel / 20, 2.0)) + 1.4 annotationView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale)) } } } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } } extension MKMapView { var zoomLevel: Double { return log2(360 * ((Double(self.frame.size.width) / 256) / self.region.span.longitudeDelta)) - 1 } }