Imposta la regione MKMapView in modo che sia centrata su due annotazioni
-
27-09-2019 - |
Domanda
Sto cercando aiuto per completare del codice sull'impostazione della regione su MKMapView in base all'annotazione della posizione corrente e a un'annotazione che ho impostato.
Voglio calcolare la distanza tra i due e impostare il centro tra i due, quindi rimpicciolire in modo che entrambi siano visibili.Sembra che funzioni bene nel simulatore, ma sfortunatamente userLocation.coordinate è fissato al quartier generale di Apple.Quando eseguo il test su un dispositivo, vedo un comportamento strano.Spesso rimpicciolisce e imposta una regione adeguata se le due annotazioni si trovano in qualche modo orizzontalmente sulla stessa latitudine, ma se la distanza verticale è maggiore, lo zoom non viene rimpicciolito correttamente.
Ho usato il codice trovato Qui, e modificato leggermente per adattarlo alle mie esigenze:
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];
Una cosa che mi ha confuso è quello che dice northEast = southWest
...
Grazie in anticipo a chiunque abbia qualche aiuto e input :)
Soluzione
questo post di blog potrebbe fornire l'intuizione di necessità
http://codisllc.com/blog/zoom-mkmapview-to -FIT-annotazioni /
-(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];
}
Altri suggerimenti
Per iOS7 in avanti il modo migliore per farlo è:
//from API docs:
//- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
[self.mapView showAnnotations:self.mapView.annotations animated:YES];
Per il mio progetto personale (precedente a iOS7) ho semplicemente aggiunto una categoria sulla classe MKMapView per incapsulare la funzionalità "area visibile" per un'operazione molto comune:impostandolo per poter vedere tutte le annotazioni attualmente caricate sull'istanza MKMapView (questo include tutti i pin che potresti aver inserito, così come la posizione dell'utente).il risultato è stato questo:
file .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
Come puoi vedere, finora ho aggiunto 2 metodi:uno per impostare la regione visibile della mappa su quella che si adatta a tutte le annotazioni attualmente caricate sull'istanza MKMapView e un altro metodo per impostarlo su qualsiasi array di oggetti.Quindi, per impostare la regione visibile di mapView, il codice sarebbe semplice come:
//the mapView instance
[self.mapView ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:animated];
Spero che ti sia d'aiuto =)
Non si abbia paura dalle prime due righe, si può ignorare ciò che è giusto di = segni, in quanto sarà sovrascritto di sotto ...
Credo che il problema è qui:
region.span.longitudeDelta = 0.0;
Swift 4 versione di Robertibiris risposta:
mapView.showAnnotations(mapView.annotations, animated: true)