2010-08-08 4 views
22

Je travaille avec MKMapView et ai tracé plusieurs points sur la carte. J'ai utilisé le MKCoordinateRegion et MKCoordinateSpan pour activer le zoom etc autour de l'un des points - mais ce n'est pas ce que je veux ...iOS MKMapViewer le zoom pour afficher tous les marqueurs

J'essaie d'utiliser quelque chose de similaire à la fonction zoom Javascript to bounds. donc tous mes points devraient être visibles à l'utilisateur. (Il y aura environ 10 points autour du Royaume-Uni) J'aimerais les montrer tous, ou si la plupart d'entre eux étaient dans la région de Londres, zoomer vers là.

Existe-t-il un moyen de résoudre ce problème par programme?

Répondre

66

Bien sûr. Vous souhaitez trouver les valeurs de latitude et de longitude les plus grandes et les plus petites parmi vos annotations (ce que vous pouvez faire en itérant sur map.annotations), puis définir la carte pour toutes les afficher.

// 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

Voici une amélioration qui tient compte de la hauteur des vues d'annotation que vous superposez sur la carte (telle que la partie supérieure de l'annotation ne lorsque son décalage de coordonnées get ne retireras est en bas pour Exemple). Ou pour généraliser plus loin, vous permet de spécifier un remplissage en pixels par opposition à un pourcentage. Il nécessite un passage en deux étapes par lequel vous trouvez les limites pour les annotations, puis vous augmentez davantage les limites pour prendre en compte votre remplissage de carte.

- (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 vous ne ciblez iOS 7 ou plus, vous pouvez maintenant utiliser:

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

modifié Réponse avec tout le code de travail parfait.

//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

C'est une vieille question et je sais que vous n'aurez peut-être pas besoin d'aide. Mais je le mets juste là pour quelqu'un qui cherche un moyen de le faire maintenant car il y a une nouvelle méthode dans MKMapView à partir de iOS 7 qui peut être utilisé. C'est à la fois propre et facile.

Déclaration

SWIFT

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

Objective-C

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

Paramètres

annotations Les annotations que vous souhaitez être visible dans la carte. YES animé si vous voulez que la région de la carte change pour être animée, ou NON si vous voulez que la carte affiche la nouvelle région immédiatement sans animations.

Discussion

L'appel de cette mise à jour de la méthode la valeur dans la propriété région et les propriétés potentiellement d'autres à reflètent la nouvelle région de la carte.

Questions connexes