2010-08-08 11 views
22

Estoy trabajando con MKMapView y he trazado varios puntos en el mapa. He usado MKCoordinateRegion y MKCoordinateSpan para activar el zoom, etc. alrededor de uno de los puntos, pero eso no es lo que quiero ...iOS MKMapVer zoom para mostrar todos los marcadores

Estoy tratando de usar algo similar a la función de zoom de Javascript a límites. entonces todos mis puntos deberían ser visibles para el usuario. (Habrá alrededor de 10 puntos en todo el Reino Unido) Me gustaría mostrarlos todos, o si la mayoría de ellos estaban en el área de Londres, haga un acercamiento a ese lugar.

¿Hay alguna manera de resolver esto programáticamente?

Respuesta

66

Sure. Desea encontrar los valores de latitud y longitud más grandes y más pequeños entre sus anotaciones (lo que puede hacer iterando sobre map.annotations), luego configure el mapa para mostrarlos todos.

// pad our map by 10% around the farthest annotations 
#define MAP_PADDING 1.1 

// we'll make sure that our minimum vertical span is about a kilometer 
// there are ~111km to a degree of latitude. regionThatFits will take care of 
// longitude, which is more complicated, anyway. 
#define MINIMUM_VISIBLE_LATITUDE 0.01 

MKCoordinateRegion region; 
region.center.latitude = (minLatitude + maxLatitude)/2; 
region.center.longitude = (minLongitude + maxLongitude)/2; 

region.span.latitudeDelta = (maxLatitude - minLatitude) * MAP_PADDING; 

region.span.latitudeDelta = (region.span.latitudeDelta < MINIMUM_VISIBLE_LATITUDE) 
    ? MINIMUM_VISIBLE_LATITUDE 
    : region.span.latitudeDelta; 

region.span.longitudeDelta = (maxLongitude - minLongitude) * MAP_PADDING; 

MKCoordinateRegion scaledRegion = [map regionThatFits:region]; 
[map setRegion:scaledRegion animated:YES]; 
14

Aquí es una mejora que tiene en cuenta la altura de las vistas de anotación que se está superponiendo en el mapa (de tal manera que la parte superior de la anotación no recibe corten durante su cota de desplazamiento es en la parte inferior de ejemplo). O para generalizar aún más, le permite especificar el relleno en píxeles en lugar de un porcentaje. Requiere un pase de dos etapas mediante el cual descubres los límites de las anotaciones, luego aumentas los límites para tener en cuenta el relleno del mapa.

- (void) zoomToAnnotationsBounds:(NSArray *)annotations { 

CLLocationDegrees minLatitude = DBL_MAX; 
CLLocationDegrees maxLatitude = -DBL_MAX; 
CLLocationDegrees minLongitude = DBL_MAX; 
CLLocationDegrees maxLongitude = -DBL_MAX; 

for (MyAnnotation *annotation in annotations) { 
      double annotationLat = annotation.coordinate.latitude; 
      double annotationLong = annotation.coordinate.longitude; 
    minLatitude = fmin(annotationLat, minLatitude); 
    maxLatitude = fmax(annotationLat, maxLatitude); 
    minLongitude = fmin(annotationLong, minLongitude); 
    maxLongitude = fmax(annotationLong, maxLongitude); 
} 

    // See function below 
[self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude]; 

// If your markers were 40 in height and 20 in width, this would zoom the map to fit them perfectly. Note that there is a bug in mkmapview's set region which means it will snap the map to the nearest whole zoom level, so you will rarely get a perfect fit. But this will ensure a minimum padding. 
UIEdgeInsets mapPadding = UIEdgeInsetsMake(40.0, 10.0, 0.0, 10.0); 
CLLocationCoordinate2D relativeFromCoord = [self.mapView convertPoint:CGPointMake(0, 0) toCoordinateFromView:self.mapView]; 

// Calculate the additional lat/long required at the current zoom level to add the padding 
CLLocationCoordinate2D topCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.top) toCoordinateFromView:self.mapView]; 
CLLocationCoordinate2D rightCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.right) toCoordinateFromView:self.mapView]; 
CLLocationCoordinate2D bottomCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.bottom) toCoordinateFromView:self.mapView]; 
CLLocationCoordinate2D leftCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.left) toCoordinateFromView:self.mapView]; 

double latitudeSpanToBeAddedToTop = relativeFromCoord.latitude - topCoord.latitude; 
double longitudeSpanToBeAddedToRight = relativeFromCoord.latitude - rightCoord.latitude; 
double latitudeSpanToBeAddedToBottom = relativeFromCoord.latitude - bottomCoord.latitude; 
double longitudeSpanToBeAddedToLeft = relativeFromCoord.latitude - leftCoord.latitude; 

maxLatitude = maxLatitude + latitudeSpanToBeAddedToTop; 
minLatitude = minLatitude - latitudeSpanToBeAddedToBottom; 

maxLongitude = maxLongitude + longitudeSpanToBeAddedToRight; 
minLongitude = minLongitude - longitudeSpanToBeAddedToLeft; 

[self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude]; 
} 

-(void) setMapRegionForMinLat:(double)minLatitude minLong:(double)minLongitude maxLat:(double)maxLatitude maxLong:(double)maxLongitude { 

    MKCoordinateRegion region; 
    region.center.latitude = (minLatitude + maxLatitude)/2; 
    region.center.longitude = (minLongitude + maxLongitude)/2; 
    region.span.latitudeDelta = (maxLatitude - minLatitude); 
    region.span.longitudeDelta = (maxLongitude - minLongitude); 

    // MKMapView BUG: this snaps to the nearest whole zoom level, which is wrong- it doesn't respect the exact region you asked for. See http://stackoverflow.com/questions/1383296/why-mkmapview-region-is-different-than-requested 
    [self.mapView setRegion:region animated:YES]; 
} 
16

Si sólo se dirigen a iOS 7 o superior ahora se puede utilizar:

- (void)showAnnotations:(NSArray *)annotations 
       animated:(BOOL)animated 
0

respuesta Modificado con todo el código perfecto estado de funcionamiento.

//Zooming the ploted Area 
- (void)zoomToAnnotationsBounds:(NSArray *)latLongArray { 
     __block CLLocationDegrees minLatitude = DBL_MAX; 
     __block CLLocationDegrees maxLatitude = -DBL_MAX; 
     __block CLLocationDegrees minLongitude = DBL_MAX; 
     __block CLLocationDegrees maxLongitude = -DBL_MAX; 

     [latLongArray enumerateObjectsUsingBlock:^(NSString *latLongObj, NSUInteger latLongIdx, BOOL *stop) { 
      latLongObj = [latLongArray objectAtIndex:latLongIdx]; 
      NSArray *latLongPoint = [latLongObj componentsSeparatedByString:@","]; 

      double annotationLat = [[latLongPoint objectAtIndex:0] doubleValue]; 
      double annotationLong = [[latLongPoint objectAtIndex:1] doubleValue]; 
      minLatitude = fmin(annotationLat, minLatitude); 
      maxLatitude = fmax(annotationLat, maxLatitude); 
      minLongitude = fmin(annotationLong, minLongitude); 
      maxLongitude = fmax(annotationLong, maxLongitude); 
     }]; 

     [self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude]; 
} 


-(void) setMapRegionForMinLat:(double)minLatitude minLong:(double)minLongitude maxLat:(double)maxLatitude maxLong:(double)maxLongitude { 

    // pad our map by 10% around the farthest annotations 

    // we'll make sure that our minimum vertical span is about a kilometer 
    // there are ~111km to a degree of latitude. regionThatFits will take care of 
    // longitude, which is more complicated, anyway. 

    MKCoordinateRegion region; 
    region.center.latitude = (minLatitude + maxLatitude)/2; 
    region.center.longitude = (minLongitude + maxLongitude)/2; 

    region.span.latitudeDelta = (maxLatitude - minLatitude) * MAP_PADDING; 

    region.span.latitudeDelta = (region.span.latitudeDelta < MINIMUM_VISIBLE_LATITUDE) 
    ? MINIMUM_VISIBLE_LATITUDE 
    : region.span.latitudeDelta; 

    region.span.longitudeDelta = (maxLongitude - minLongitude) * MAP_PADDING; 

    MKCoordinateRegion scaledRegion = [regionsMapView regionThatFits:region]; 
    [regionsMapView setRegion:scaledRegion animated:YES]; 

} 
7

Es una vieja pregunta y sé que podría no necesitar ayuda. Pero lo estoy presentando para cualquiera que esté buscando una forma de hacerlo ahora, ya que hay un nuevo método en MKMapView a partir de iOS 7 que se puede usar. Es limpio y fácil.

Declaración

SWIFT

func showAnnotations(_ annotations: [AnyObject]!, 
      animated animated: Bool) 

Objective-C

- (void)showAnnotations:(NSArray *)annotations 
       animated:(BOOL)animated 

Parámetros

anotaciones Las anotaciones que desea ser visible en el mapa . si desea que el cambio de región del mapa sea animado, o NO si desea que el mapa muestre la nueva región inmediatamente sin animaciones.

Discusión

llamar a este método actualizaciones el valor de la propiedad región y potencialmente otras propiedades a reflejan la nueva región del mapa.

Cuestiones relacionadas