2010-08-08 6 views
22

Я работаю с MKMapView и наметил несколько точек на карте. Я использовал и MKCoordinateSpan, чтобы включить масштабирование и т. Д. Вокруг одной из точек - но это не то, что я хочу ...iOS MKMapView увеличить, чтобы показать все маркеры

Я пытаюсь использовать что-то похожее на функцию Javascript для масштабирования. поэтому все мои точки должны быть видны пользователю. (В Великобритании будет около 10 баллов) Я бы хотел показать их всем, или, если большинство из них находились в районе Лондона, увеличьте масштаб.

Есть ли способ работать с этим программным путем?

ответ

66

Несомненно. Вы хотите найти самые большие и наименьшие значения широты и долготы среди ваших аннотаций (которые вы можете сделать, итерации по map.annotations), а затем установите карту, чтобы показать все из них.

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

Вот усовершенствование, которое принимает во внимание высоту взглядов аннотаций, которые вы наложенные на карту (например, что верхняя часть аннотации не получает отрезать, когда его смещения координат находится в нижнюю части для пример). Или для дальнейшего обобщения, вы можете указать заполнение в пикселях в противоположность проценту. Для этого требуется двухэтапный проход, в котором вы узнаете границы аннотаций, затем вы дополнительно увеличиваете границы, чтобы учесть наложение вашей карты.

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

Если вы только против IOS 7 или выше, теперь вы можете использовать:

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

Modified ответ со всем Совершенным рабочим кодом.

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

Это старый вопрос, и я знаю, что вам может не понадобиться помощь. Но я просто размещаю его для тех, кто ищет способ сделать это сейчас, так как есть новый метод в MKMapView с iOS 7, который можно использовать. Он чист и прост.

Декларация

СВИФТ

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

Objective-C

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

Параметры

Аннотации аннотаций, которые вы хотите, чтобы быть видимым в карте. анимированный YES, если вы хотите, чтобы область области карты была анимированной или НЕТ, если вы хотите, чтобы карта отображала новую область сразу без анимации.

Обсуждение

Вызов этого метода обновления значение в собственности региона и потенциально другие свойства отражают новую область карты.