การวางตำแหน่ง MKMapView เพื่อแสดงคำอธิบายประกอบหลายรายการพร้อมกัน


94

ฉันมีคำอธิบายประกอบหลายรายการที่ต้องการเพิ่มลงใน MKMapView ของฉัน (สามารถเป็น 0-n รายการโดยที่ n โดยทั่วไปจะอยู่ที่ประมาณ 5) ฉันสามารถเพิ่มคำอธิบายประกอบได้ แต่ฉันต้องการปรับขนาดแผนที่ให้พอดีกับคำอธิบายประกอบทั้งหมดบนหน้าจอพร้อมกันและฉันไม่แน่ใจว่าจะทำอย่างไร

ฉันกำลังดูอยู่-regionThatFits:แต่ไม่ค่อยแน่ใจว่าจะทำอย่างไรกับมัน ฉันจะโพสต์รหัสเพื่อแสดงสิ่งที่ฉันมีจนถึงตอนนี้ ฉันคิดว่านี่น่าจะเป็นงานที่ตรงไปตรงมา แต่ตอนนี้ฉันรู้สึกหนักใจกับ MapKit เล็กน้อย

- (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];
}

สังเกตว่าทั้งหมดนี้เกิดขึ้นเมื่อฉันได้รับการอัปเดตตำแหน่ง ... ฉันไม่รู้ว่าเป็นสถานที่ที่เหมาะสมหรือไม่ ถ้าไม่เป็นสถานที่ที่ดีกว่านี้? -viewDidLoadเหรอ?

ขอบคุณล่วงหน้า.

คำตอบ:



137

ลิงค์โพสต์โดยจิมคือตอนนี้ตายไปแล้ว แต่ผมก็สามารถที่จะหารหัส (ซึ่งผมได้บุ๊คมาร์คที่ไหนสักแห่ง) หวังว่านี่จะช่วยได้

- (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
ฉันสามารถจูบคุณ แค่นี้ก็ช่วยฉันได้มากแล้ว ฉันเพิ่มรหัสที่ด้านบนเพื่อจัดการสถานที่ 1 แห่ง มันใกล้ชิดและเป็นส่วนตัวขึ้นเล็กน้อย ฉันจะโพสต์เป็นการตอบกลับเนื่องจากความคิดเห็นมักจะเคี้ยวโค้ด
Michael Reed

ขอบคุณมาก. ฉันเพิ่มสิ่งนี้ลงในคลาสย่อยของMKMapViewและเปลี่ยนวิธีการเป็น- (void) zoomToFitAnnotations:(BOOL)animated. ทำงานได้อย่างสมบูรณ์แบบ!
simonbs

1
มันทำงานได้ดีมาก ยังมีประโยชน์ คุณสามารถเปลี่ยนค่าการซูมออกหรือซูมเข้า ดังนั้น region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; /// เปลี่ยนค่า เมื่อคุณเพิ่มค่า: ซูมออก ........ เมื่อคุณลดค่า: ซูมเข้าเช่น region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 4.1;
Erhan Demirci

1
@ MR.Mustafa: ใช้งานได้ดีเยี่ยม! แต่ฉันคิดว่าการแก้ปัญหาก็เพียงพอแล้ว ดังนั้นโปรดอธิบายวิธีการทำงานของฉัน หรือผ่านลิงค์ใด ๆ ขออภัยถ้าฉันงี่เง่าฉันเป็นมือใหม่ กรุณาสนับสนุน ขอบคุณ
Siddarth Hailstorm

1
@ มุสตาฟา ... ขอบคุณที่บันทึกวันของฉันไว้
Vvk

133

ทำไมต้องซับซ้อน?

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
ไม่น่าเชื่อว่าง่ายกว่าสะอาดกว่าและง่ายกว่าทางเลือกที่โพสต์ไว้มากแค่ไหน ในความเป็นจริงคุณสามารถทำให้สิ่งนี้ง่ายขึ้นได้อีกเพราะไม่จำเป็นต้องแปลงเป็น MKCoordinateRegion เพียงแค่เรียกใช้ setVisibleMapRect: บน MKMapView ของคุณด้วย MKMapRect ที่คุณสร้างที่นี่
lensovet

2
บางครั้งคำอธิบายประกอบจะติดอยู่ที่ด้านบนของแผนที่และมองไม่เห็น ข้อมูลใดเกี่ยวกับแนวทางที่ดีที่สุดในการเพิ่มการซูมหลังจากสร้าง MKCoordinateRegion แล้ว
Kyle C

3
@KyleC[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(20.0f, 20.0f, 20.0f, 20.0f) animated:animated];
ผู้ใช้

คุณสร้างCLLocationCoordinate2D *coordsอาร์เรย์ได้อย่างไร? ใช้malloc()?
Hlung

3
@KyleC. ฉันเพิ่มสิ่งนี้ไปก่อนที่จะกลับมาrซึ่งโดยทั่วไปจะซูมออก 20 เปอร์เซ็นต์CGFloat 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

ฉันได้ทำบางสิ่งที่คล้ายกับสิ่งนี้เพื่อย่อ (หรือเข้า) ไปยังพื้นที่ที่มีคำอธิบายประกอบจุดและตำแหน่งปัจจุบัน คุณสามารถขยายสิ่งนี้ได้โดยการวนซ้ำคำอธิบายประกอบของคุณ

ขั้นตอนพื้นฐานมีดังนี้

  • คำนวณ lat / long ขั้นต่ำ
  • คำนวณ lat / long สูงสุด
  • สร้างวัตถุ CLLocation สำหรับสองจุดนี้
  • คำนวณระยะทางระหว่างจุด
  • สร้างพื้นที่โดยใช้จุดกึ่งกลางระหว่างจุดและระยะทางที่แปลงเป็นองศา
  • ผ่านภูมิภาคไปยัง MapView เพื่อปรับเปลี่ยน
  • ใช้พื้นที่ที่ปรับแล้วเพื่อตั้งค่าภูมิภาค MapView
    -(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];
    }

ดูเหมือนว่าจะไป ขอบคุณ!
jbrennan

1
จัดการเพื่อให้สิ่งนี้ใช้งานได้โดยใช้MKCoordinateRegionMake: gist.github.com/1599700ในกรณีที่ยังมีใครอยากทำแบบนี้
chakrit

region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0; ขอบคุณสำหรับสิ่งนี้
Tony

สิ่งนี้ใช้ได้กับจุดทั้งสองข้างของเส้นเมริเดียนหรือไม่? เส้นศูนย์สูตร?
Eliot

1
รหัสนี้จะวางตำแหน่งไว้นอกหน้าจอเมื่อสถานที่มีค่า y ใกล้เคียงกัน ตัวอย่างการแสดงตำแหน่งสองตำแหน่งที่ (50, -4) & (100, -3) จะซูมแผนที่ไกลเกินไปโดยวางพิกัดไว้ทางด้านซ้ายและขวาของหน้าจอ
ผู้ใช้

21

ฉันมีคำตอบที่แตกต่างออกไป ฉันกำลังจะใช้อัลกอริทึมการซูมให้พอดีกับตัวเอง แต่ฉันคิดว่า Apple ต้องมีวิธีทำในสิ่งที่เราต้องการโดยไม่ต้องทำงานมากนัก การใช้ API doco อย่างรวดเร็วแสดงให้เห็นว่าฉันสามารถใช้ MKPolygon เพื่อทำสิ่งที่จำเป็น:

/* 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];
}

หวังว่านี่จะช่วยได้


ไม่มีปัญหา. มักจะมีวิธีที่ดีกว่าถ้าคุณเต็มใจและมีเวลาที่จะใช้กับมัน
PKCLsoft

ฉันพบว่าสิ่งนี้ทำให้หมุดอยู่ใกล้กับขอบหน้าจอมากเกินไป ลองเพิ่ม annotationsRegion.span.latitudeDelta = annotationsRegion.span.latitudeDelta * kEventMapDetailBorderFactor; ก่อน setRegion
Adam Eberbach

คุณพูดถูก @AdamEberbach แต่ดูเหมือนว่าคลิปของคุณจะมีค่าคงที่ที่ไม่สามารถใช้ได้ คุณพบค่าที่ให้เส้นขอบ "ดี" รอบหมุดหรือไม่?
PKCLsoft

คำตอบของ Code Commander ด้านล่างเกี่ยวกับการใช้วิธี showAnnotations ใหม่กับ iOS7 ช่วยเพิ่มระยะขอบที่ดีซึ่งทำงานได้ดีขึ้นแม้ว่ารหัสนี้จะเย็นกว่า
James Toomey

14

คุณสามารถทำได้ด้วยวิธีนี้ ..

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

จากข้อมูลและคำแนะนำจากทุกคนที่ฉันได้รับดังต่อไปนี้ ขอบคุณสำหรับทุกคนในการสนทนานี้สำหรับการมีส่วนร่วม :) สิ่งนี้จะไปในมุมมอง Controller ที่มี mapView

- (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]; 
}

สิ่งนี้ควรได้รับการโหวตมากขึ้น เป๊ะมากและตรงประเด็น
Natasha

6

การใช้ Swift รูปหลายเหลี่ยมและช่องว่างเพิ่มเติมบางอย่างฉันใช้สิ่งต่อไปนี้:

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 (... ) ฉันทำคณิตศาสตร์ด้วยตัวเอง ...
CodeReaper

5

ในกรณีของฉันฉันเริ่มต้นด้วยวัตถุ CLLocation และสร้างคำอธิบายประกอบสำหรับแต่ละรายการ
ฉันต้องวางคำอธิบายประกอบสองรายการเท่านั้นดังนั้นฉันจึงมีวิธีง่ายๆในการสร้างอาร์เรย์ของจุด แต่สามารถขยายได้อย่างง่ายดายเพื่อสร้างอาร์เรย์ที่มีความยาวตามอำเภอใจโดยกำหนดชุดของ CLLocations

นี่คือการใช้งานของฉัน (ไม่จำเป็นต้องสร้าง MKMapPoints):

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

นี่คือ SWIFT Equivalent (ยืนยันการทำงานใน: 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
สวัสดี iOS_Developer ขอบคุณสำหรับการแปลง Swift สำหรับฉันมันใช้ไม่ได้เพราะฉันคิดว่าคุณขาด "fmax" สองตัวแทนที่จะเป็น "fmin" สำหรับ topLeftCoordinate.latitude และ bottomRightCoordinate.longitude
Philipp Otto

3

มีวิธีใหม่ใน 'MKMapView' ใน iOS 7 ที่คุณสามารถใช้ได้

คำประกาศ

SWIFT

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

วัตถุประสงค์ -C

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

พารามิเตอร์

คำอธิบายประกอบคำอธิบายประกอบที่คุณต้องการให้ปรากฏในแผนที่ ภาพเคลื่อนไหวใช่หากคุณต้องการให้พื้นที่แผนที่เปลี่ยนเป็นภาพเคลื่อนไหวหรือไม่หากคุณต้องการให้แผนที่แสดงพื้นที่ใหม่ทันทีโดยไม่มีภาพเคลื่อนไหว

อภิปรายผล

การเรียกใช้เมธอดนี้จะอัปเดตค่าในคุณสมบัติภูมิภาคและคุณสมบัติอื่น ๆ ที่อาจเกิดขึ้นเพื่อสะท้อนถึงขอบเขตแผนที่ใหม่


3

ฉันรู้ว่านี่เป็นคำถามเก่า แต่หากคุณต้องการแสดงคำอธิบายประกอบทั้งหมดบนแผนที่ให้ใช้สิ่งนี้:

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

2

วิธีแก้ปัญหาวิธีหนึ่งที่เป็นไปได้คือการวัดระยะห่างระหว่างตำแหน่งปัจจุบันและคำอธิบายประกอบทั้งหมดและใช้เมธอด MKCoordinateRegionMakeWithDistance เพื่อสร้างพื้นที่ที่มีระยะห่างมากกว่าคำอธิบายประกอบที่อยู่ไกลที่สุดเล็กน้อย

แน่นอนว่าสิ่งนี้จะช้าลงเมื่อคุณเพิ่มคำอธิบายประกอบมากขึ้น


ฉันกำลังอ่านส่วนความคิดเห็นเพื่อตรวจสอบตัวเองเท่านั้น ดีใจที่มีคนคิดแบบที่ฉันทำ :-) เนื่องจากฉันเพิ่มคำอธิบายประกอบเพียงสองคำ (จุดเริ่มต้นและจุดสิ้นสุด) ฉันจึงไม่รู้สึกถึงความเชื่องช้า
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(ตอนนี้อยู่ใน Swift)

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

เพิ่ม if clause เล็กน้อยเพื่อจัดการ 1 ตำแหน่ง - เพื่อเพิ่มลงในข้อมูลโค้ด cound ของ mustufa ใช้ฟังก์ชัน zoomToAnnotation ของ pkclSoft สำหรับสิ่งนั้น:

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

รหัสนี้ใช้ได้กับฉันมันแสดงหมุดทั้งหมดที่มีตำแหน่งปัจจุบันหวังว่านี่จะช่วยคุณได้

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 ที่นี่เราสามารถเก็บ UserLocation และคำอธิบายประกอบที่กำหนดเองเพื่อให้พอดีกับ MKMapView

 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
}

ป้อนคำอธิบายภาพที่นี่


0

ฉันหวังว่าอย่างน้อยนี่จะเกี่ยวข้องนี่คือสิ่งที่ฉันรวบรวมไว้สำหรับ Mono (จากคำตอบของ pkclSoft):

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 ฉันเขียนหมวดหมู่สำหรับ MKMapView เพื่อเพิ่มระยะขอบและข้ามคำอธิบายประกอบตำแหน่งของผู้ใช้:

@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

เนื่องจากฉันไม่สามารถแสดงความคิดเห็นเกี่ยวกับคำตอบได้ฉันจึงต้องการเพิ่มความสะดวกสบายของฉันลงในคำตอบของ @ me2 (เนื่องจากฉันคิดว่าเป็นแนวทางที่สง่างามที่สุดพบได้ที่นี่)

สำหรับโปรเจ็กต์ส่วนตัวของฉันฉันเพียงแค่เพิ่มหมวดหมู่ในคลาส 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]; 

ฉันหวังว่ามันจะช่วยได้ =)


0

พิจารณาส่วนขยายนี้:

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

เวอร์ชัน 5 ที่รวดเร็ว:

   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)
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.