MKMapView'i aynı anda birden çok ek açıklamayı gösterecek şekilde konumlandırma


94

MKMapView'uma eklemek istediğim birkaç ek açıklamam var (n'nin genellikle 5 civarında olduğu 0-n öğe olabilir). Ek açıklamaları iyi bir şekilde ekleyebilirim, ancak haritayı ekrandaki tüm açıklamaları aynı anda sığacak şekilde yeniden boyutlandırmak istiyorum ve bunu nasıl yapacağımı bilmiyorum.

Bakıyorum -regionThatFits:ama onunla ne yapacağımdan pek emin değilim. Şimdiye kadar sahip olduğum şeyi göstermek için bir kod göndereceğim. Bunun genel olarak basit bir görev olduğunu düşünüyorum ancak şu ana kadar MapKit ile biraz bunalmış hissediyorum.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{

location = newLocation.coordinate;
//One location is obtained.. just zoom to that location

MKCoordinateRegion region;
region.center = location;

//Set Zoom level using Span
MKCoordinateSpan span;
span.latitudeDelta = 0.015;
span.longitudeDelta = 0.015;
region.span = span;
// Set the region here... but I want this to be a dynamic size
// Obviously this should be set after I've added my annotations
[mapView setRegion:region animated:YES];

// Test data, using these as annotations for now
NSArray *arr = [NSArray arrayWithObjects:@"one", @"two", @"three", @"four", nil];
float ex = 0.01;
for (NSString *s in arr) {
    JBAnnotation *placemark = [[JBAnnotation alloc] initWithLat:(location.latitude + ex) lon:location.longitude];
    [mapView addAnnotation:placemark];
    ex = ex + 0.005;
}
    // What do I do here?
    [mapView setRegion:[mapView regionThatFits:region] animated:YES];
}

Dikkat edin, bunların hepsi bir konum güncellemesi aldığımda oluyor ... Bunu yapmak için uygun bir yer mi bilmiyorum. Değilse, daha iyi bir yer neresi olabilir? -viewDidLoad?

Şimdiden teşekkürler.

Yanıtlar:



137

Bağlantı (ı Yerimlerine bir yerlerde vardı) Jim tarafından gönderildi şimdi öldü, ama ben kodu bulabildim. Bu yardımcı olur umarım.

- (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(id<MKAnnotation> 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;      

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

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

14
Seni öpebilirdim. Bu bana zaman kazandırdı. 1 konumu işlemek için yukarıya kodu ekledim. Biraz yakından ve kişiselleşti. Yorumlar kodu çiğneme eğiliminde olduğu için bunu bir yanıt olarak göndereceğim.
Michael Reed

Çok teşekkür ederim. Bunu bir alt sınıfa ekledim MKMapViewve yöntemi olarak değiştirdim - (void) zoomToFitAnnotations:(BOOL)animated. Mükemmel çalışıyor!
simonbs

1
çok iyi çalışıyor. ayrıca kullanışlıdır. yakınlaştırma veya uzaklaştırma değerini değiştirebilirsiniz. yani region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; /// değeri değiştir. değeri artırdığınızda: uzaklaştırın ........ değeri düşürdüğünüzde: yakınlaştırma örneğin: region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 4.1;
Erhan Demirci

1
@ MR.Mustafa: Çalışıyor, harika! Ama sorunu çözmenin yeterli olduğunu düşünmüyorum. Bu yüzden lütfen biri bana nasıl çalıştığını açıklasın. Veya herhangi bir bağlantı aracılığıyla. Eğer aptal isem özür dilerim, acemiyim. Pls desteği. Teşekkürler
Siddarth Hailstorm

1
@Mustafa ... Teşekkürler günümü kurtardı.
Vvk

133

Neden bu kadar karmaşık?

MKCoordinateRegion coordinateRegionForCoordinates(CLLocationCoordinate2D *coords, NSUInteger coordCount) {
    MKMapRect r = MKMapRectNull;
    for (NSUInteger i=0; i < coordCount; ++i) {
        MKMapPoint p = MKMapPointForCoordinate(coords[i]);
        r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
    }
    return MKCoordinateRegionForMapRect(r);
}

6
Bunun, yayınlanan alternatiflerden ne kadar daha basit, daha temiz ve daha kolay olduğu inanılmaz. Aslında, bunu daha da basitleştirebilirsiniz çünkü MKCoordinateRegion'a dönüştürmeye gerek yoktur - sadece burada oluşturduğunuz MKMapRect ile MKMapView'unuzda setVisibleMapRect: çağırın.
lensovet

2
Ek açıklamalar bazen haritanın üst kısmına yapıştırılır ve görünmez. MKCoordinateRegion oluşturulduktan sonra yakınlaştırmayı artırmak için en iyi yaklaşımla ilgili herhangi bir girdi var mı?
Kyle C

3
@KyleC[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(20.0f, 20.0f, 20.0f, 20.0f) animated:animated];
kullanıcı

CLLocationCoordinate2D *coordsDiziyi nasıl oluşturuyorsunuz ? Kullanıyor malloc()musunuz?
Hlung

3
@KyleC. Ben dönmeden önce bu ilave rtemelde yüzde 20 uzaklaştırmak hangiCGFloat zoomOutPercent = 0.2f; r = MKMapRectMake(r.origin.x-r.size.width*zoomOutPercent, r.origin.y-r.size.height*zoomOutPercent, r.size.width*(1+zoomOutPercent*2), r.size.height*(1+zoomOutPercent*2));
Loozie

45

Bir nokta notu ve mevcut konumu içeren bir alanı uzaklaştırmak (veya yakınlaştırmak) için buna benzer bir şey yaptım. Ek açıklamalarınızda döngü yaparak bunu genişletebilirsiniz.

Temel adımlar şunlardır:

  • Min enlem / boylam değerini hesaplayın
  • Maksimum enlem / boylam değerini hesaplayın
  • Bu iki nokta için CLLocation nesneleri oluşturun
  • Noktalar arasındaki mesafeyi hesaplayın
  • Noktalar arasındaki merkez noktasını ve dereceye dönüştürülmüş mesafeyi kullanarak bölge oluşturun
  • Ayarlamak için bölgeyi MapView'a geçirin
  • MapView bölgesini ayarlamak için ayarlanmış bölgeyi kullanın
    -(IBAction)zoomOut:(id)sender {

        CLLocationCoordinate2D southWest = _newLocation.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 getDistanceFrom: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;

        _savedRegion = [_mapView regionThatFits:region];
        [_mapView setRegion:_savedRegion animated:YES];

        [locSouthWest release];
        [locNorthEast release];
    }

Gidilecek yol bu gibi görünüyor. Teşekkürler!
jbrennan

1
Bu kullanarak çalışmak için başardı MKCoordinateRegionMake: gist.github.com/1599700 durumda herkes hala bu şekilde yapmak istiyorum.
chakrit

region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0; Bunun için teşekkürler
Tony

Bu, meridyenin her iki tarafındaki noktalarla çalışır mı? Ekvator?
Eliot

1
Bu kod, konumlar benzer bir y değerine sahip olduğunda konumları ekranın dışına yerleştirir. Örnek, (50, -4) & (100, -3) 'te iki konumun gösterilmesi haritayı çok uzağa yakınlaştıracak ve koordinatları ekranın sol ve sağ tarafına yerleştirecektir.
kullanıcı

21

Farklı bir cevabım var. Sığdırmak için yakınlaştırma algoritmasını kendim uygulayacaktım, ancak Apple'ın istediğimiz şeyi çok fazla çalışma yapmadan yapmanın bir yolu olması gerektiğini düşündüm . API doco'yu kullanmak, ihtiyaç duyulan şeyi yapmak için MKPolygon'u kullanabileceğimi çabucak gösterdi:

/* this simply adds a single pin and zooms in on it nicely */
- (void) zoomToAnnotation:(MapAnnotation*)annotation {
    MKCoordinateSpan span = {0.027, 0.027};
    MKCoordinateRegion region = {[annotation coordinate], span};
    [mapView setRegion:region animated:YES];
}

/* This returns a rectangle bounding all of the pins within the supplied
   array */
- (MKMapRect) getMapRectUsingAnnotations:(NSArray*)theAnnotations {
    MKMapPoint points[[theAnnotations count]];

    for (int i = 0; i < [theAnnotations count]; i++) {
        MapAnnotation *annotation = [theAnnotations objectAtIndex:i];
        points[i] = MKMapPointForCoordinate(annotation.coordinate);
    }

    MKPolygon *poly = [MKPolygon polygonWithPoints:points count:[theAnnotations count]];

    return [poly boundingMapRect];
}

/* this adds the provided annotation to the mapview object, zooming 
   as appropriate */
- (void) addMapAnnotationToMapView:(MapAnnotation*)annotation {
    if ([annotations count] == 1) {
        // If there is only one annotation then zoom into it.
        [self zoomToAnnotation:annotation];
    } else {
        // If there are several, then the default behaviour is to show all of them
        //
        MKCoordinateRegion region = MKCoordinateRegionForMapRect([self getMapRectUsingAnnotations:annotations]);

        if (region.span.latitudeDelta < 0.027) {
            region.span.latitudeDelta = 0.027;
        }

        if (region.span.longitudeDelta < 0.027) {
            region.span.longitudeDelta = 0.027;
        }
        [mapView setRegion:region];
    }

    [mapView addAnnotation:annotation];
    [mapView selectAnnotation:annotation animated:YES];
}

Bu yardımcı olur umarım.


Sorun yok. İstekliysen ve bunun için harcayacak zamanın varsa, genellikle daha iyi bir yol vardır.
PKCLsoft

Bunun iğneleri ekranın kenarına biraz fazla yaklaştırdığını buldum. AnnotationsRegion.span.latitudeDelta = annotationsRegion.span.latitudeDelta * kEventMapDetailBorderFactor; setRegion'dan hemen önce.
Adam Eberbach

Haklısın @AdamEberbach, ama görünüşe göre klibinde mevcut olmayan bir sabit var. İğnelerin etrafında "güzel" bir sınır sağlayan bir değer buldunuz mu?
PKCLsoft

Kod Komutanı'nın iOS7 ile yeni showAnnotations yöntemini kullanmayla ilgili aşağıdaki cevabı, bu kod daha havalı olsa da aslında daha iyi çalışan güzel bir marj ekler.
James Toomey

14

bu şekilde de yapabilirsiniz ..

// Position the map so that all overlays and annotations are visible on screen.
MKMapRect regionToDisplay = [self mapRectForAnnotations:annotationsToDisplay];
if (!MKMapRectIsNull(regionToDisplay)) myMapView.visibleMapRect = regionToDisplay;

- (MKMapRect) mapRectForAnnotations:(NSArray*)annotationsArray
{
    MKMapRect mapRect = MKMapRectNull;

    //annotations is an array with all the annotations I want to display on the map
    for (id<MKAnnotation> annotation in annotations) { 

        MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);

        if (MKMapRectIsNull(mapRect)) 
        {
            mapRect = pointRect;
        } else 
        {
            mapRect = MKMapRectUnion(mapRect, pointRect);
        }
    }

     return mapRect;
}

13

Herkesten gelen bilgi ve önerilere dayanarak aşağıdakileri ortaya çıkardım. Katkıda bulundukları için bu tartışmadaki herkese teşekkürler :) Bu, mapView'i içeren Denetleyici görünümüne gider.

- (void)zoomToFitMapAnnotations { 

if ([self.mapView.annotations count] == 0) return; 

int i = 0;
MKMapPoint points[[self.mapView.annotations count]];

//build array of annotation points
for (id<MKAnnotation> annotation in [self.mapView annotations])
        points[i++] = MKMapPointForCoordinate(annotation.coordinate);

MKPolygon *poly = [MKPolygon polygonWithPoints:points count:i];

[self.mapView setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect]) animated:YES]; 
}

Bu daha fazla oy almalı. Çok kesin ve isabetli.
Natasha

6

Swift, bir çokgen ve bazı ekstra dolgu kullanarak aşağıdakileri kullandım:

func zoomToFit() {
    var allLocations:[CLLocationCoordinate2D] = [
        CLLocationCoordinate2D(latitude: 32.768805, longitude: -117.167119),
        CLLocationCoordinate2D(latitude: 32.770480, longitude: -117.148385),
        CLLocationCoordinate2D(latitude: 32.869675, longitude: -117.212929)
    ]

    var poly:MKPolygon = MKPolygon(coordinates: &allLocations, count: allLocations.count)

    self.mapView.setVisibleMapRect(poly.boundingMapRect, edgePadding: UIEdgeInsetsMake(40.0, 40.0, 40.0, 40.0), animated: false)
}


setVisibleMapRect (...). Matematiği kendim yapıyordum ... kötü.
CodeReaper

5

Benim durumumda, CLLocation nesneleriyle başlıyorum ve her biri için ek açıklamalar oluşturuyorum.
Yalnızca iki ek açıklama yerleştirmem gerekiyor, bu nedenle nokta dizisini oluşturmak için basit bir yaklaşımım var, ancak bir dizi CLLokasyonu verildiğinde keyfi uzunlukta bir dizi oluşturmak için kolayca genişletilebilir.

İşte benim uygulamam (MKMapPoints oluşturmayı gerektirmez):

//start with a couple of locations
CLLocation *storeLocation = store.address.location.clLocation;
CLLocation *userLocation = [LBLocationController sharedController].currentLocation;

//build an array of points however you want
CLLocationCoordinate2D points[2] = {storeLocation.coordinate, userLocation.coordinate};

//the magic part
MKPolygon *poly = [MKPolygon polygonWithCoordinates:points count:2];
[self.mapView setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect])];

4

Mustafa'nın Cevapları için SWIFT Eşdeğeri (Çalıştığı Onaylandı: Xcode6.1, SDK 8.2):

func zoomToFitMapAnnotations() {
    if self.annotations.count == 0 {return}

    var topLeftCoordinate = CLLocationCoordinate2D(latitude: -90, longitude: 180)
    var bottomRightCoordinate = CLLocationCoordinate2D(latitude: 90, longitude: -180)

    for object in self.annotations {
        if let annotation = object as? MKAnnotation {
            topLeftCoordinate.longitude = fmin(topLeftCoordinate.longitude, annotation.coordinate.longitude)
            topLeftCoordinate.latitude = fmax(topLeftCoordinate.latitude, annotation.coordinate.latitude)
            bottomRightCoordinate.longitude = fmax(bottomRightCoordinate.longitude, annotation.coordinate.longitude)
            bottomRightCoordinate.latitude = fmin(bottomRightCoordinate.latitude, annotation.coordinate.latitude)
        }
    }

    let center = CLLocationCoordinate2D(latitude: topLeftCoordinate.latitude - (topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 0.5, longitude: topLeftCoordinate.longitude - (topLeftCoordinate.longitude - bottomRightCoordinate.longitude) * 0.5)

    print("\ncenter:\(center.latitude) \(center.longitude)")
    // Add a little extra space on the sides
    let span = MKCoordinateSpanMake(fabs(topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 1.01, fabs(bottomRightCoordinate.longitude - topLeftCoordinate.longitude) * 1.01)
    print("\nspan:\(span.latitudeDelta) \(span.longitudeDelta)")

    var region = MKCoordinateRegion(center: center, span: span)


    region = self.regionThatFits(region)

    self.setRegion(region, animated: true)

}

1
Merhaba iOS_Developer. Swift dönüşümü için teşekkürler. Benim için çalışmıyor çünkü topLeftCoordinate.latitude ve bottomRightCoordinate.longitude için "fmin" yerine iki "fmax" eksik olduğunu düşünüyorum.
Philipp Otto

3

İOS 7'den itibaren kullanabileceğiniz 'MKMapView'de yeni bir yöntem var

Beyanname

SWIFT

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

HEDEF-C

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

Parametreler

ek açıklamalar Haritada görünmesini istediğiniz ek açıklamalar. animasyonlu EVET, harita bölgesi değişikliğinin animasyonlu olmasını istiyorsanız veya haritanın yeni bölgeyi animasyon olmadan hemen görüntülemesini istiyorsanız HAYIR.

Tartışma

Bu yöntemin çağrılması, bölge özelliğindeki değeri ve potansiyel olarak diğer özellikleri yeni harita bölgesini yansıtacak şekilde günceller.


3

Bunun eski bir soru olduğunu biliyorum, ancak tüm ek açıklamaları ZATEN haritada görüntülemek istiyorsanız şunu kullanın:

 mapView.showAnnotations(mapView.annotations, animated: true)

2

Olası bir çözüm, mevcut konum ile tüm açıklamalar arasındaki mesafeyi ölçmek ve en uzak detaylandırmadan biraz daha büyük bir mesafeye sahip bir bölge yapmak için MKCoordinateRegionMakeWithDistance yöntemini kullanmak olabilir.

Bu, elbette daha fazla ek açıklama ekledikçe yavaşlayacaktır.


Sadece kendimi doğrulamak için yorumlar bölümünden geçiyordum. Başkasının benim düşündüğüm gibi düşünmesine sevindim :-) Yalnızca iki açıklama eklediğim için (başlangıç ​​ve bitiş noktası), hiç yavaşlık hissetmedim.
thandasoru

2
- (void)zoomToFitMapAnnotations {

if ([self.mapview.annotations count] == 0) return;

int i = 0;
MKMapPoint points[[self.mapview.annotations count]];

//build array of annotation points
for (id<MKAnnotation> annotation in [self.mapview annotations])
    points[i++] = MKMapPointForCoordinate(annotation.coordinate);

MKPolygon *poly = [MKPolygon polygonWithPoints:points count:i];

[self.mapview setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect]) animated:YES];
}

2

me2(Şimdi Swift'de) tarafından verilen mükemmel cevaba göre

func coordinateRegionForCoordinates(coords: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
    var rect: MKMapRect = MKMapRectNull
    for coord in coords {
        let point: MKMapPoint = MKMapPointForCoordinate(coord)
        rect = MKMapRectUnion(rect, MKMapRectMake(point.x, point.y, 0, 0))
    }
    return MKCoordinateRegionForMapRect(rect)
}

1

Mustufa'nın kod parçacığına eklemek için 1 konumu işlemek için küçük bir if cümlesi eklendi. Bunun için pkclSoft'un zoomToAnnotation işlevi kullanıldı:

if ([mapView.annotations count] == 1){
    MKCoordinateSpan span = {0.027, 0.027};
    region.span = span;
    CLLocationCoordinate2D singleCoordinate = [[mapView.annotations objectAtIndex:0] coordinate];
    region.center.latitude = singleCoordinate.latitude;
    region.center.longitude = singleCoordinate.longitude;
}
else
{
    // mustufa's code
}

1

bu kod benim için çalışıyor, mevcut konumdaki tüm pinleri gösteriyor, umarım bu size yardımcı olur,

func setCenterForMap() {
    var mapRect: MKMapRect = MKMapRectNull
    for loc in mapView.annotations {
        let point: MKMapPoint = MKMapPointForCoordinate(loc.coordinate)
        print( "location is : \(loc.coordinate)");
        mapRect = MKMapRectUnion(mapRect, MKMapRectMake(point.x,point.y,0,0))
    }
    if (locationManager.location != nil) {
        let point: MKMapPoint = MKMapPointForCoordinate(locationManager.location!.coordinate)
        print( "Cur location is : \(locationManager.location!.coordinate)");
        mapRect = MKMapRectUnion(mapRect, MKMapRectMake(point.x,point.y,0,0))
    }

    mapView.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsetsMake(40.0, 40.0, 40.0, 40.0), animated: true)

}

1

Stéphane de Luca'nın cevabına ek olarak . Burada UserLocation ve Özel ek açıklamaları MKMapView'a uyacak şekilde tutabiliriz

 private func centerViewOnUserLocation() {
    
    if selectedLatitudeFromPreviousVC?.description != nil && selectedLongitudeFromPreviousVC?.description != nil {
        
        if let location = locationManager.location?.coordinate {
            let region = regionFor(coordinates: [
                CLLocationCoordinate2D(latitude: selectedLatitudeFromPreviousVC!, longitude: selectedLongitudeFromPreviousVC!),
                location])
            mkmapView.setRegion(region, animated: true)
        }
    } else {
        if let location = locationManager.location?.coordinate {
            let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
            mkmapView.setRegion(region, animated: true)
        }
    }
}

private func regionFor(coordinates coords: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
    var r = MKMapRect.null

    for i in 0 ..< coords.count {
        let p = MKMapPoint(coords[i])
        r = r.union(MKMapRect(x: p.x, y: p.y, width: 0, height: 0))
    }

    var coordinateRegion = MKCoordinateRegion(r)
    coordinateRegion.span.latitudeDelta *= 1.5
    coordinateRegion.span.longitudeDelta *= 1.5
    return coordinateRegion
}

görüntü açıklamasını buraya girin


0

Umarım bu en azından alakalı olur, Mono için bir araya getirdiğim şey budur (pkclSoft'un cevabına dayanarak):

void ZoomMap (MKMapView map)
{
    var annotations = map.Annotations;

    if (annotations == null || annotations.Length == 0) 
        return;

    var points = annotations.OfType<MapAnnotation> ()
                            .Select (s => MKMapPoint.FromCoordinate (s.Coordinate))
                            .ToArray ();            

    map.SetVisibleMapRect(MKPolygon.FromPoints (points).BoundingMapRect, true); 
}

0
CLLocationCoordinate2D min = CLLocationCoordinate2DMake(99999.0, 99999.0);
CLLocationCoordinate2D max = CLLocationCoordinate2DMake(-99999.0, -99999.0);

// find max/min....

// zoom to cover area
// TODO: Maybe better using a MKPolygon which can calculate its own fitting region.
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((max.latitude + min.latitude) / 2.0, (max.longitude + min.longitude) / 2.0);
MKCoordinateSpan span = MKCoordinateSpanMake(max.latitude - min.latitude, max.longitude - min.longitude);
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);

[_mapView setRegion:[_mapView regionThatFits:region] animated:YES];

0

Me2 yanıtına dayanarak, bazı kenar boşlukları eklemek ve kullanıcı konumu açıklamasını atlamak için MKMapView için bir kategori yazdım:

@interface MKMapView (ZoomToFitAnnotations)
- (void)zoomToFitAnnotations:(BOOL)animated;
@end

@implementation MKMapView (ZoomToFitAnnotations)
- (void)zoomToFitAnnotations:(BOOL)animated {
    if (self.annotations.count == 0)
        return;

    MKMapRect rect = MKMapRectNull;
    for (id<MKAnnotation> annotation in self.annotations) {
        if ([annotation isKindOfClass:[MKUserLocation class]] == false) {
            MKMapPoint point = MKMapPointForCoordinate(annotation.coordinate);
            rect = MKMapRectUnion(rect, MKMapRectMake(point.x, point.y, 0, 0));
        }
    }

    MKCoordinateRegion region = MKCoordinateRegionForMapRect(rect);
    region.span.longitudeDelta *= 2; // Margin
    region.span.latitudeDelta *= 2; // Margin
    [self setRegion:region animated:animated];
}
@end

0

Bir cevaba yorum yapamayacağım için, @ me2'nin cevabına biraz da rahatlık katmak istiyorum (çünkü bunun burada bulunan en zarif yaklaşım olduğunu düşündüm).

Kişisel projem için, çok yaygın bir işlem için "görünür alan" işlevselliğini kapsüllemek için MKMapView sınıfına bir kategori ekledim: MKMapView örneğinde şu anda yüklü olan tüm ek açıklamaları görebilmek için ayar. sonuç şuydu:

.h dosyası

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

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


@end

.m dosyası

#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

Gördüğünüz gibi, şimdiye kadar 2 yöntem ekledim: biri, haritanın görünür bölgesini MKMapView örneğindeki tüm mevcut ek açıklamalara uyan birime ayarlamak için ve onu herhangi bir nesne dizisine ayarlamak için başka bir yöntem. Dolayısıyla, mapView'ün görünür bölgesini ayarlamak için kod şu kadar basit olacaktır:

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

Umarım yardımcı olur =)


0

Bu uzantıyı düşünün:

extension MKCoordinateRegion {
    init(locations: [CLLocationCoordinate2D], marginMultiplier: Double = 1.1) {
        let mapRect = locations.reduce(MKMapRect(), {
            let point = MKMapPointForCoordinate($1)
            let rect = MKMapRect(origin: point, size: MKMapSize(width: 0.0, height: 0.0))
            return MKMapRectUnion($0, rect)
        })

        var coordinateRegion = MKCoordinateRegionForMapRect(mapRect)
        coordinateRegion.span.latitudeDelta *= marginMultiplier
        coordinateRegion.span.longitudeDelta *= marginMultiplier
        self = coordinateRegion
    }
}

0

Hızlı bir 5 versiyonu:

   func regionFor(coordinates coords: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
        var r = MKMapRect.null

        for i in 0 ..< coords.count {
            let p = MKMapPoint(coords[i])

            r = r.union(MKMapRect(x: p.x, y: p.y, width: 0, height: 0))
        }

        return MKCoordinateRegion(r)
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.