2010-10-29 5 views
0

Я ищу некоторую помощь с завершением некоторого кода при настройке области на MKMapView на основе текущей аннотации местоположения и аннотации, которую я установил.Установите область MKMapView в центр на две аннотации

Я хочу рассчитать расстояние между ними и установить центр между ними, а затем уменьшить масштаб, чтобы оба были в поле зрения. Кажется, он отлично работает в Simulator для меня, но, к сожалению, userLocation.coordinate установлен на Apple HQ. Когда я тестирую устройство, я вижу странное поведение. Часто он уменьшает масштаб и устанавливает правильную область, если две аннотации несколько горизонтальны на одной и той же широте, но если вертикальное расстояние больше, то оно не масштабируется должным образом.

Я использовал код нашел here, и отредактирован немного, чтобы соответствовать моим потребностям:

CLLocationCoordinate2D southWest = mapView.userLocation.coordinate; 
CLLocationCoordinate2D northEast = southWest; 

southWest.latitude = MIN(southWest.latitude, annotation.coordinate.latitude); 
southWest.longitude = MIN(southWest.longitude, annotation.coordinate.longitude); 

northEast.latitude = MAX(northEast.latitude, annotation.coordinate.latitude); 
northEast.longitude = MAX(northEast.longitude, annotation.coordinate.longitude); 

CLLocation *locSouthWest = [[CLLocation alloc] initWithLatitude:southWest.latitude longitude:southWest.longitude]; 
CLLocation *locNorthEast = [[CLLocation alloc] initWithLatitude:northEast.latitude longitude:northEast.longitude]; 

// This is a diag distance (if you wanted tighter you could do NE-NW or NE-SE) 
CLLocationDistance meters = [locSouthWest distanceFromLocation:locNorthEast]; 

MKCoordinateRegion region; 
region.center.latitude = (southWest.latitude + northEast.latitude)/2.0; 
region.center.longitude = (southWest.longitude + northEast.longitude)/2.0; 
region.span.latitudeDelta = meters/111319.5; 
region.span.longitudeDelta = 0.0; 

MKCoordinateRegion savedRegion = [mapView regionThatFits:region]; 
[mapView setRegion:savedRegion animated:YES]; 

[locSouthWest release]; 
[locNorthEast release]; 

Единственное, что меня смутило то, что он говорит northEast = southWest ...

Заранее спасибо всем, который получил некоторую помощь и вход :)

ответ

-1

этот блог размещение может предоставить вам с пониманием, чтобы нужно

http://codisllc.com/blog/zoom-mkmapview-to-fit-annotations/

-(void)zoomToFitMapAnnotations:(MKMapView*)mapView 
{ 
    if([mapView.annotations count] == 0) 
     return; 

    CLLocationCoordinate2D topLeftCoord; 
    topLeftCoord.latitude = -90; 
    topLeftCoord.longitude = 180; 

    CLLocationCoordinate2D bottomRightCoord; 
    bottomRightCoord.latitude = 90; 
    bottomRightCoord.longitude = -180; 

    for(MapAnnotation* annotation in mapView.annotations) 
    { 
     topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude); 
     topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude); 

     bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude); 
     bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude); 
    } 

    MKCoordinateRegion region; 
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5; 
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5; 
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides 
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides 

    region = [mapView regionThatFits:region]; 
    [mapView setRegion:region animated:YES]; 
} 
+0

Отлично! Дельты были проблемой, которую я вижу. Спасибо! – runmad

+1

К сожалению, эта страница, кажется, не отвечает. Кто-нибудь имеет кешированную версию страницы? Благодаря! – jowie

+0

@jowie Мне удалось найти кешированную версию страницы, используя обратную машину. Надеюсь, это поможет. http://web.archive.org/web/20100612181520/http://codisllc.com/blog/zoom-mkmapview-to-fit-annotations – avelis

0

Не пугайтесь от двух первых строк, вы можете игнорировать то, что это право = знаков, так как он будет перезаписан ниже ...

Я думаю, что вопрос здесь:

region.span.longitudeDelta = 0.0; 
+0

Да, ссылка Аарона выше имеет дельта, правильно рассчитанную и, похоже, она ее разрешила. Просто нужно немного подправить дополнительную маржу, но код идеален! – runmad

1

для iOS7 вперед лучший способ сделать это:

//from API docs: 
//- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0); 
[self.mapView showAnnotations:self.mapView.annotations animated:YES]; 

для моего личного проекта (до И.О. S7) Я просто добавил категорию в класс MKMapView, чтобы инкапсулировать функциональность «видимой области» для очень распространенной операции: установить ее, чтобы она могла видеть все загруженные в данный момент аннотации в экземпляре MKMapView (это включает в себя столько контактов, сколько вы возможно, разместили, а также местоположение пользователя). результат был таков:

.h файл

#import <MapKit/MapKit.h> 

@interface MKMapView (Extensions) 

-(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated; 
-(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated; 


@end 

.m файл

#import "MKMapView+Extensions.h" 

@implementation MKMapView (Extensions) 

/** 
* Changes the currently visible portion of the map to a region that best fits all the currently loadded annotations on the map, and it optionally animates the change. 
* 
* @param animated is the change should be perfomed with an animation. 
*/ 
-(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated 
{ 
    MKMapView * mapView = self; 

    NSArray * annotations = mapView.annotations; 

    [self ij_setVisibleRectToFitAnnotations:annotations animated:animated]; 

} 


/** 
* Changes the currently visible portion of the map to a region that best fits the provided annotations array, and it optionally animates the change. 
    All elements from the array must conform to the <MKAnnotation> protocol in order to fetch the coordinates to compute the visible region of the map. 
* 
* @param annotations an array of elements conforming to the <MKAnnotation> protocol, holding the locations for which the visible portion of the map will be set. 
* @param animated wether or not the change should be perfomed with an animation. 
*/ 
-(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated 
{ 
    MKMapView * mapView = self; 

    MKMapRect r = MKMapRectNull; 
    for (id<MKAnnotation> a in annotations) { 
     ZAssert([a conformsToProtocol:@protocol(MKAnnotation)], @"ERROR: All elements of the array MUST conform to the MKAnnotation protocol. Element (%@) did not fulfill this requirement", a); 
     MKMapPoint p = MKMapPointForCoordinate(a.coordinate); 
     //MKMapRectUnion performs the union between 2 rects, returning a bigger rect containing both (or just one if the other is null). here we do it for rects without a size (points) 
     r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0)); 
    } 

    [mapView setVisibleMapRect:r animated:animated]; 

} 

@end 

Как вы можете видеть, я добавил 2 метода до сих пор: один для установки видимой области карта соответствует той, которая соответствует всем загруженным в настоящий момент аннотациям экземпляра MKMapView, а также другому методу, чтобы установить его в любой массив объектов. Так, чтобы установить видимую область в MAPview в код затем будет так же просто, как:

//the mapView instance 
    [self.mapView ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:animated]; 

Я надеюсь, что это помогает =)

Смежные вопросы