Định vị MKMapView để hiển thị nhiều chú thích cùng một lúc


92

Tôi có một số chú thích mà tôi muốn thêm vào MKMapView của mình (nó có thể là 0-n mục, trong đó n thường là khoảng 5). Tôi có thể thêm các chú thích cũng được, nhưng tôi muốn thay đổi kích thước bản đồ để vừa với tất cả các chú thích trên màn hình cùng một lúc và tôi không chắc cách thực hiện việc này.

Tôi đã xem xét -regionThatFits:nhưng tôi không chắc phải làm gì với nó. Tôi sẽ đăng một số mã để hiển thị những gì tôi có cho đến nay. Tôi nghĩ rằng đây là một nhiệm vụ nhìn chung đơn giản nhưng tôi cảm thấy hơi quá tải với MapKit cho đến nay.

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

Lưu ý, tất cả điều này xảy ra khi tôi nhận được bản cập nhật vị trí ... Tôi không biết đó có phải là nơi thích hợp để thực hiện việc này hay không. Nếu không, nơi nào sẽ là một nơi tốt hơn? -viewDidLoad?

Cảm ơn trước.

Câu trả lời:



137

Các liên kết đăng bởi Jim tại là chết, nhưng tôi đã có thể tìm thấy mã (mà tôi đã ở đâu đó đã đánh dấu). Hi vọng điêu nay co ich.

- (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
Tôi có thể hôn bạn. Điều này chỉ giúp tôi tiết kiệm rất nhiều thời gian. Tôi đã thêm mã vào phần trên để xử lý 1 vị trí. Nó có một chút gần gũi và cá nhân. Tôi sẽ đăng điều đó như một phản hồi vì các bình luận có xu hướng nhai lại mã.
Michael Reed,

Cảm ơn rât nhiều. Tôi đã thêm điều này vào một lớp con của MKMapViewvà thay đổi phương thức thành - (void) zoomToFitAnnotations:(BOOL)animated. Hoạt động hoàn hảo!
simonbs

1
nó hoạt động rất tốt. nó cũng hữu ích. bạn có thể thay đổi thu nhỏ hoặc phóng to giá trị. so region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; /// thay đổi giá trị. khi bạn tăng giá trị: thu nhỏ ........ khi bạn giảm giá trị: phóng to ví dụ: region.span.latitudeDelta = fabs (topLeftCoord.latitude - bottomRightCoord.latitude) * 4.1;
Erhan Demirci

1
@ MR.Mustafa: Nó đang hoạt động, thật tuyệt vời! Nhưng tôi không nghĩ rằng giải quyết vấn đề là đủ. Vì vậy, xin một số giải thích cho tôi cách nó hoạt động. Hoặc thông qua bất kỳ liên kết nào. Xin lỗi nếu tôi ngớ ngẩn, tôi là người mới bắt đầu. Xin hỗ trợ. Cảm ơn bạn
Siddarth trận bão lớn

1
@Mustafa ... Cảm ơn nó đã cứu một ngày của tôi.
Vvk

133

Tại sao lại phức tạp như vậy?

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
Không thể tin được điều này đơn giản, sạch sẽ và dễ dàng hơn nhiều so với các lựa chọn thay thế đã đăng. trên thực tế, bạn có thể đơn giản hóa điều này hơn nữa vì không cần phải chuyển đổi sang MKCoosystemRegion - chỉ cần gọi setVibleMapRect: trên MKMapView của bạn với MKMapRect mà bạn tạo ở đây.
lensovet

2
Các chú thích đôi khi bị kẹt ở đầu bản đồ và không hiển thị. Bất kỳ đầu vào nào về cách tiếp cận tốt nhất để tăng zoom sau khi MKCoosystemRegion được tạo?
Kyle C

3
@KyleC[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(20.0f, 20.0f, 20.0f, 20.0f) animated:animated];
người dùng

Làm thế nào để bạn tạo CLLocationCoordinate2D *coordsmảng? Sử dụng malloc()?
Hlung

3
@KyleC. Tôi thêm này để trước khi trở về rmà về cơ bản thu nhỏ 20 phần trămCGFloat 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

44

Tôi đã thực hiện một việc tương tự như vậy để thu nhỏ (hoặc thu nhỏ) khu vực bao gồm chú thích điểm và vị trí hiện tại. Bạn có thể mở rộng điều này bằng cách lặp qua các chú thích của mình.

Các bước cơ bản là:

  • Tính toán kinh độ / kinh độ tối thiểu
  • Tính toán kinh độ / độ dài tối đa
  • Tạo đối tượng CLLocation cho hai điểm này
  • Tính khoảng cách giữa các điểm
  • Tạo vùng bằng cách sử dụng điểm trung tâm giữa các điểm và khoảng cách được chuyển đổi thành độ
  • Chuyển vùng vào MapView để điều chỉnh
  • Sử dụng vùng đã điều chỉnh để đặt vùng 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];
    }

Đây có vẻ như là con đường để đi. Cảm ơn!
jbrennan

1
Được quản lý để điều này hoạt động bằng cách sử dụng MKCoordinateRegionMake: gist.github.com/1599700 trong trường hợp có ai đó vẫn muốn làm theo cách này.
chakrit

region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0; Cảm ơn vì nó
Tony

Điều này có hoạt động với các điểm ở hai bên của kinh tuyến không? Đường xích đạo?
Eliot

1
Mã này đặt các vị trí ra ngoài màn hình khi các vị trí có giá trị y tương tự. Ví dụ, hiển thị hai vị trí tại (50, -4) & (100, -3) sẽ thu phóng bản đồ quá xa, đặt các tọa độ lệch khỏi bên trái và bên phải của màn hình.
người dùng

21

Tôi có một câu trả lời khác. Tôi đã định tự mình triển khai thuật toán thu phóng để phù hợp, nhưng tôi nhận ra rằng Apple phải có cách để làm những gì chúng tôi muốn mà không cần quá nhiều công sức. Việc sử dụng API doco nhanh chóng cho thấy rằng tôi có thể sử dụng MKPolygon để thực hiện những việc cần thiết:

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

Hi vọng điêu nay co ich.


Không vấn đề gì. Thường có một cách tốt hơn nếu bạn sẵn sàng và có thời gian để dành cho nó.
PKCLsoft

Tôi thấy điều này không đặt các ghim quá gần với cạnh của màn hình. Thử thêm annotationsRegion.span.latitudeDelta = annotationsRegion.span.latitudeDelta * kEventMapDetailBorderFactor; ngay trước setRegion.
Adam Eberbach

Bạn đúng @AdamEberbach, nhưng có vẻ như clip của bạn bao gồm một hằng số không khả dụng. Bạn có tìm thấy giá trị cung cấp đường viền "đẹp" xung quanh các chân không?
PKCLsoft

Câu trả lời của Code Commander bên dưới về việc sử dụng phương thức showAnnotations mới với iOS7 bổ sung thêm một lề tốt, thực sự hoạt động tốt hơn, mặc dù mã này mát hơn.
James Toomey

14

bạn cũng có thể làm theo cách này ..

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

Dựa trên thông tin và gợi ý từ mọi người, tôi đã đưa ra những điều sau đây. Cảm ơn tất cả mọi người trong cuộc thảo luận này đã đóng góp :) Điều này sẽ đi trong Chế độ xem Controller có chứa 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]; 
}

Điều này sẽ nhận được nhiều phiếu bầu hơn. Rất chính xác và chính xác.
Natasha

5

Trong trường hợp của tôi, tôi đang bắt đầu với các đối tượng CLLocation và tạo chú thích cho từng đối tượng trong số chúng.
Tôi chỉ cần đặt hai chú thích, vì vậy tôi có một cách tiếp cận đơn giản để xây dựng mảng điểm, nhưng nó có thể dễ dàng mở rộng để xây dựng một mảng có độ dài tùy ý cho trước một tập hợp các CLLocations.

Đây là cách triển khai của tôi (không yêu cầu tạo 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])];

5

Sử dụng Swift, một đa giác và một số đệm bổ sung, tôi đã sử dụng như sau:

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)
}


setVbrokenMapRect (...). Tôi đã tự làm toán ... kém.
CodeReaper

3

Có một phương pháp mới trong 'MKMapView' kể từ iOS 7 mà bạn có thể sử dụng

Tờ khai

NHANH

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

MỤC TIÊU-C

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

Thông số

chú thích Chú thích mà bạn muốn hiển thị trên bản đồ. động CÓ nếu bạn muốn vùng bản đồ thay đổi thành hoạt ảnh hoặc KHÔNG nếu bạn muốn bản đồ hiển thị vùng mới ngay lập tức mà không có hoạt ảnh.

Thảo luận

Gọi phương thức này sẽ cập nhật giá trị trong thuộc tính vùng và các thuộc tính tiềm năng khác để phản ánh vùng bản đồ mới.


3

Tôi biết đây là một câu hỏi cũ nhưng nếu bạn muốn hiển thị tất cả các chú thích trên bản đồ, hãy sử dụng cái này:

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

3

Đây là SWIFT tương đương (Đã xác nhận hoạt động trong: Xcode6.1, SDK 8.2) cho Câu trả lời của Mustafa:

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
Xin chào iOS_Developer. Cảm ơn bạn đã chuyển đổi Swift. Đối với tôi, nó không hoạt động vì tôi nghĩ rằng bạn đang thiếu hai "fmax" thay vì "fmin" cho topLeftCoosystem.latitude và bottomRightCoosystem.longitude.
Philipp Otto

2

Một giải pháp khả thi có thể là đo khoảng cách giữa vị trí hiện tại và tất cả các chú thích và sử dụng phương pháp MKCoprisRegionMakeWithDistance để tạo một vùng có khoảng cách lớn hơn một chút so với chú thích xa nhất.

Điều này tất nhiên sẽ chậm hơn nếu bạn thêm nhiều chú thích hơn.


Tôi đã xem qua phần bình luận chỉ để xác nhận bản thân mình. Rất vui khi ai đó nghĩ theo cách tôi đã làm :-) Vì tôi chỉ thêm hai chú thích (điểm bắt đầu và điểm kết thúc) nên tôi không cảm thấy chậm.
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

Dựa trên câu trả lời xuất sắc của me2(bây giờ bằng 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

Đã thêm một chút mệnh đề if để xử lý 1 vị trí- để thêm vào đoạn mã cound của mustufa. Đã sử dụng chức năng zoomToAnnotation của pkclSoft cho việc đó:

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

mã này phù hợp với tôi, nó hiển thị tất cả các chân với vị trí hiện tại, hy vọng điều này sẽ giúp bạn,

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)

}

0

Tôi hy vọng điều này ít nhất có liên quan, đây là những gì tôi đã tổng hợp lại cho Mono (dựa trên câu trả lời của 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

Dựa trên phản hồi của me2, tôi đã viết một danh mục cho MKMapView để thêm một số lợi nhuận và bỏ qua chú thích vị trí của người dùng:

@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

Vì tôi không thể bình luận về một câu trả lời, tôi muốn thêm một chút tiện lợi của mình vào câu trả lời của @ me2 (vì tôi nghĩ rằng đó là cách tiếp cận thanh lịch nhất Được tìm thấy ở đây).

Đối với dự án cá nhân của tôi, tôi chỉ cần thêm một danh mục trên lớp MKMapView để đóng gói chức năng "khu vực hiển thị" cho một hoạt động chung của phiên bản: cài đặt để có thể xem tất cả các chú thích hiện đang được tải trên cá thể MKMapView. kết quả là:

tệp .h

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

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


@end

tệp .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

Như bạn có thể thấy, cho đến nay tôi đã thêm 2 phương pháp: một phương pháp để thiết lập vùng hiển thị của bản đồ thành một phương thức phù hợp với tất cả các chú thích hiện đang tải trên cá thể MKMapView và một phương pháp khác để đặt nó thành bất kỳ mảng đối tượng nào. Vì vậy, để đặt vùng hiển thị của mapView, mã sau đó sẽ đơn giản như sau:

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

Tôi hy vọng nó sẽ giúp =)


0

Hãy xem xét phần mở rộng này:

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

Một phiên bản 5 nhanh chóng:

   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)
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.