Thu phóng MKMapView để phù hợp với chân chú thích?


193

Tôi đang sử dụng MKMapView và đã thêm một số chân chú thích vào bản đồ khoảng 5-10 km. Khi tôi chạy ứng dụng, bản đồ của tôi bắt đầu thu nhỏ để hiển thị toàn thế giới, cách tốt nhất để thu phóng bản đồ để các chân phù hợp với chế độ xem là gì?

EDIT: Suy nghĩ ban đầu của tôi sẽ là sử dụng MKCoordinateRegionMake và tính toán trung tâm tọa độ, longitudeDelta và latitudeDelta từ các chú thích của tôi. Tôi khá chắc chắn rằng điều này sẽ hoạt động, nhưng tôi chỉ muốn kiểm tra xem tôi không thiếu thứ gì rõ ràng.

Mã được thêm vào, BTW: FGLocation là một lớp phù hợp với MKAnnotation, locationFake là một NSMutableArraytrong những đối tượng này. Bình luận luôn được chào đón ....

- (MKCoordinateRegion)regionFromLocations {
    CLLocationCoordinate2D upper = [[locationFake objectAtIndex:0] coordinate];
    CLLocationCoordinate2D lower = [[locationFake objectAtIndex:0] coordinate];

    // FIND LIMITS
    for(FGLocation *eachLocation in locationFake) {
        if([eachLocation coordinate].latitude > upper.latitude) upper.latitude = [eachLocation coordinate].latitude;
        if([eachLocation coordinate].latitude < lower.latitude) lower.latitude = [eachLocation coordinate].latitude;
        if([eachLocation coordinate].longitude > upper.longitude) upper.longitude = [eachLocation coordinate].longitude;
        if([eachLocation coordinate].longitude < lower.longitude) lower.longitude = [eachLocation coordinate].longitude;
    }

    // FIND REGION
    MKCoordinateSpan locationSpan;
    locationSpan.latitudeDelta = upper.latitude - lower.latitude;
    locationSpan.longitudeDelta = upper.longitude - lower.longitude;
    CLLocationCoordinate2D locationCenter;
    locationCenter.latitude = (upper.latitude + lower.latitude) / 2;
    locationCenter.longitude = (upper.longitude + lower.longitude) / 2;

    MKCoordinateRegion region = MKCoordinateRegionMake(locationCenter, locationSpan);
    return region;
}

10
Lưu ý iOS 7: ShowAnnotations: animation: phương thức mới có thể giúp bạn tránh tính toán vùng thủ công này.

Câu trả lời:


123

Bạn đã hiểu đúng.

Tìm vĩ độ và kinh độ tối đa và tối thiểu của bạn, áp dụng một số số học đơn giản và sử dụng MKCoordinateRegionMake.

Đối với iOS 7 trở lên, hãy sử dụng showAnnotations:animated:, từ MKMapView.h:

// Position the map such that the provided array of annotations are all visible to the fullest extent possible. 
- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);

158
Dành cho iOS 7 trở lên (Giới thiệu MKMapView.h): // Position the map such that the provided array of annotations are all visible to the fullest extent possible. - (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
Abhishek Bedi

1
Điều này hoạt động tốt nhưng đôi khi khi tôi phóng to (trong bản đồ) sau đó cố gắng căn giữa nó (sử dụng nút gọi phương thức này) thì có vẻ như nó không hoạt động.
RPM

5
Điều quan trọng cần lưu ý là showAnnotationscũng thêm các chú thích vào bản đồ, ngay cả khi chú thích cho vị trí đó đã tồn tại.
Eneko Alonso

@EnekoAlonso Bạn có thể giải quyết vấn đề này bằng cách gọi removeAnnotations(_ annotations:)ngay sau đóshowAnnotations(_ annotations:animated)
Alain Stulz

1
Cũng đáng chú ý là trong khi showAnnotations đặt khu vực để hiển thị chú thích, khu vực vẫn được điều chỉnh để phù hợp với tỷ lệ khung hình; và điều này sẽ thường xuyên loại trừ một số chú thích. Cũng lưu ý rằng showAnnotations là giải pháp đúng duy nhất được trình bày ở đây; không có câu trả lời nào khác thậm chí cố gắng xử lý các chú thích kéo dài dòng ngày quốc tế.
Gordon Dove

335

Đây là cái tôi tìm thấy ở đây làm việc cho tôi:

(EDIT: Tôi đã cập nhật giải pháp bằng cách sử dụng đề xuất của @ Micah để tăng điểmRect lên 0,1 để đảm bảo rằng trực tràng không bị vô cùng nhỏ!)

MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations)
{
    MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
    MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
    zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
[mapView setVisibleMapRect:zoomRect animated:YES];

 

Bạn cũng có thể cập nhật thông tin này để bao gồm pin người dùngLocation bằng cách thay thế dòng đầu tiên bằng:

MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);

4
Thực sự tốt đẹp. Bạn không cần phải kiểm tra là hoàn toàn. MKMapRectUnion làm điều này cho bạn. Từ các tài liệu: "Nếu một trong hai hình chữ nhật là null, phương thức này trả về hình chữ nhật khác."
Felix Lamouroux

37
Giải pháp rất hay !!! Đây là một liên lạc nhỏ để thêm một số phần đệm: double inset = -zoomRect.size. Thong * 0.1; [self.mapView setVisibleMapRect: MKMapRectInset (zoomRect, inet, inet) hoạt hình: CÓ];
Craig B

1
Tuyệt vời! Bổ sung tiềm năng: nếu bạn muốn loại trừ 'chú thích vị trí hiện tại', chỉ cần thêm một câu lệnh if trong vòng lặp for: if (! [Chú thích làKindOfClass: [lớp MKUserLocation]]) {// Thực hiện tại đây}
kgaidis

2
Giải pháp @CraigB cho phần đệm là tuyệt vời, nhưng nó không hoạt động tốt khi đường dẫn thẳng đứng, ví dụ như di chuyển từ nam sang bắc, để khắc phục điều này bằng cách sử dụng double inset = MIN (-zoomRect.size. Thong * 0.1, -zoomRect.size. chiều cao * 0,1);
Farhad Malekpour

1
Cải tiến với phần đệm: double insetWidth = -zoomRect.size. Thong * 0.2; gấp đôi insetHeight = -zoomRect.size.height * 0.2; MKMapRect insetRect = MKMapRectInset (zoomRect, insetWidth, insetHeight); Sau đó sử dụng insertRect mới này
dulgan

121

Apple đã thêm một phương pháp mới cho iOS 7 để đơn giản hóa cuộc sống một chút.

[mapView showAnnotations:yourAnnotationArray animated:YES];

Bạn có thể dễ dàng kéo từ một mảng được lưu trữ trong chế độ xem bản đồ:

yourAnnotationArray = mapView.annotations;

và nhanh chóng điều chỉnh máy ảnh quá!

mapView.camera.altitude *= 1.4;

điều này sẽ không hoạt động trừ khi người dùng đã cài đặt iOS 7+ hoặc OS X 10.9+. kiểm tra hoạt hình tùy chỉnh ở đây


Tôi không chắc liệu đây có phải là do một số yếu tố khác trong quá trình triển khai của mình không, nhưng tôi thấy rằng điều showAnnotationsđó không thực hiện gần như phóng to / thu nhỏ các chú thích như khi thực hiện thủ công, vì vậy tôi đã mắc kẹt với hướng dẫn sử dụng.
Ted Avery

1
thử nhân độ cao của camera với một phần của một, như mapView.camera.altitude * = .85; để có cái nhìn gần hơn
Ryan Berg

Tôi cũng thấy điều này hữu ích để chọn các chú thích bên ngoài khu vực bản đồ hiển thị hiện tại. Theo mặc định, MapView không chọn các chú thích không nhìn thấy được. Gọi showAnnotations với một mảng các chú thích không nhìn thấy được của bạn, trước khi gọi selectAnnotation và bản đồ sẽ cập nhật khu vực có thể xem được.
MandisaW

42

Tôi sử dụng mã này và hoạt động tốt cho tôi:

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

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

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

    for(MapViewAnnotation *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 = [aMapView regionThatFits:region];
    [mapView setRegion:region animated:YES];
}

Không làm việc cho: 2 phần tử 0: CLLocationCoordine2D - vĩ độ: 46.969995730376894 - kinh độ: -109.2494943434474 1: CLLocationCoordine2D - vĩ độ: 63.23212154333072
Olexiy Pyvovarov

23

Trong Swift sử dụng

mapView.showAnnotations(annotationArray, animated: true)

Trong mục tiêu c

[mapView showAnnotations:annotationArray animated:YES];

2
Nếu các chú thích đã được đặt trên mapView, bạn có thể tham khảo chúng trực tiếp với:mapView.showAnnotations(mapView.annotations, animated: true)
Justin Vallely

14

Tôi đã chuyển đổi câu trả lời của Rafael Moreira. Tín dụng đến với anh ta. Đối với những bạn đang tìm kiếm phiên bản Swift, đây là đoạn mã:

 func zoomToFitMapAnnotations(aMapView: MKMapView) {
    guard aMapView.annotations.count > 0 else {
        return
    }
    var topLeftCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
    topLeftCoord.latitude = -90
    topLeftCoord.longitude = 180
    var bottomRightCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
    bottomRightCoord.latitude = 90
    bottomRightCoord.longitude = -180
    for annotation: MKAnnotation in myMap.annotations as! [MKAnnotation]{
        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)
    }

    var region: MKCoordinateRegion = MKCoordinateRegion()
    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.4
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.4
    region = aMapView.regionThatFits(region)
    myMap.setRegion(region, animated: true)
}

14

Swift 3 Đây là cách chính xác để phù hợp với tất cả các chú thích trong bản đồ.

func zoomMapaFitAnnotations() {

        var zoomRect = MKMapRectNull
        for annotation in mapview.annotations {

            let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)

            let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)

            if (MKMapRectIsNull(zoomRect)) {
                zoomRect = pointRect
            } else {
                zoomRect = MKMapRectUnion(zoomRect, pointRect)
            }
        }
        self.mapview.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(50, 50, 50, 50), animated: true)

    }

@ArshadShaik Chỉnh sửa được đề xuất của bạn đã bị từ chối, nếu bạn muốn cung cấp câu trả lời mới cho Swift 4.2, hãy thoải mái, nhưng thêm nó dưới dạng câu trả lời, không phải bằng cách chỉnh sửa nó vào bài đăng của người dùng khác.
Nick

13

@ giải pháp của jowie hoạt động tuyệt vời. Một lưu ý, nếu một bản đồ chỉ có một chú thích, bạn sẽ kết thúc với một bản đồ được thu nhỏ hoàn toàn. Tôi đã thêm 0,1 vào kích thước chỉnh lưu để đảm bảo setVisibleMapRect có thứ gì đó để phóng to.

MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);

12

Nếu bạn đang tìm kiếm iOS 8 trở lên , cách đơn giản nhất là đặt var layoutMargins: UIEdgeInsets { get set }chế độ xem bản đồ của bạn trước khi gọifunc showAnnotations(annotations: [MKAnnotation], animated: Bool)

Chẳng hạn (Swift 2.1):

@IBOutlet weak var map: MKMapView! {
    didSet {
        map.delegate = self
        map.mapType = .Standard
        map.pitchEnabled = false
        map.rotateEnabled = false
        map.scrollEnabled = true
        map.zoomEnabled = true
    }
}

// call 'updateView()' when viewWillAppear or whenever you set the map annotations
func updateView() {
    map.layoutMargins = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25)
    map.showAnnotations(map.annotations, animated: true)
}

12

Tôi đã tạo một tiện ích mở rộng để hiển thị tất cả các chú thích bằng cách sử dụng một số mã từ đây và ở đó nhanh chóng. Điều này sẽ không hiển thị tất cả các chú thích nếu chúng không thể được hiển thị ngay cả ở mức thu phóng tối đa.

import MapKit

extension MKMapView {
    func fitAllAnnotations() {
        var zoomRect = MKMapRectNull;
        for annotation in annotations {
            let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
            let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
            zoomRect = MKMapRectUnion(zoomRect, pointRect);
        }
        setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50), animated: true)
    }
}

Tôi quản lý để có được kết quả tốt hơn bằng cách thay đổi các UIEdgeInsetsMaketham số, giá trị từ 30 đến 100 là tốt cho tôi. Tôi đã thử nghiệm bằng iPhone SE i) S 10.2 Simulator. Mã ví dụ : setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(100, 100, 100, 100), animated: true). Lưu ý, Mã này hoạt động trong Swift 3 và XCode 8.2.1.
nyxee

8

Đã thêm vòng lặp If này trong vòng lặp for để loại trừ ghim vị trí người dùng khỏi phương thức này (bắt buộc trong trường hợp của tôi và có thể cả những người khác)

if (![annotation isKindOfClass:[MKUserLocation class]] ) {

//Code Here...

}

8

Dành cho iOS 7 trở lên (Giới thiệu MKMapView.h):

// Position the map such that the provided array of annotations are all visible to the fullest extent possible.          

- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);

nhận xét từ - Abhishek Bedi

Bạn chỉ cần gọi:

 [yourMapView showAnnotations:@[yourAnnotation] animated:YES];

Chỉ để tham khảo, văn bản NS_AVAILABLE đã có trong đó bởi vì vào tháng 1 năm 2011, việc có iOS 7 trên thiết bị là không có khả năng và NS_AVAILABLE đã bảo vệ ứng dụng khỏi sự cố hoặc lỗi xây dựng.
Matthew Frederick

5

Trong Swift

    var zoomRect = MKMapRectNull;

    for i in 0..<self.map.annotations.count {

        let annotation: MKAnnotation = self.map.annotations[i]

        let annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }

    self.map.setVisibleMapRect(zoomRect, animated: true)

5
    var zoomRect: MKMapRect = MKMapRect.null
    for annotation in mapView.annotations {
        let annotationPoint = MKMapPoint(annotation.coordinate)
        let pointRect = MKMapRect(x: annotationPoint.x, y: annotationPoint.y, width: 0.1, height: 0.1)
        zoomRect = zoomRect.union(pointRect)
    }
    mapView.setVisibleMapRect(zoomRect, animated: true)

// Đã chỉnh sửa cho nhanh 5


4

Cảm ơn jowie tôi đã cập nhật danh mục cũ của mình thành giải pháp thanh lịch hơn. Chia sẻ hoàn thành, gần như sao chép và dán giải pháp sẵn sàng

MKMapView + Chú thíchRegion.h

#import <MapKit/MapKit.h>

@interface MKMapView (AnnotationsRegion)

-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated;
-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding;

-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated;
-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding;

@end

MKMapView + Chú thíchRegion.m

#import "MKMapView+AnnotationsRegion.h"

@implementation MKMapView (AnnotationsRegion)

-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated{
    [self updateRegionForCurrentAnnotationsAnimated:animated edgePadding:UIEdgeInsetsZero];
}
-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding{
    [self updateRegionForAnnotations:self.annotations animated:animated edgePadding:edgePadding];
}

-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated{
    [self updateRegionForAnnotations:annotations animated:animated edgePadding:UIEdgeInsetsZero];
}
-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding{
    MKMapRect zoomRect = MKMapRectNull;
    for(id<MKAnnotation> annotation in annotations){
        MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }
    [self setVisibleMapRect:zoomRect edgePadding:edgePadding animated:animated];
}

@end

Hy vọng nó sẽ giúp được ai đó và cảm ơn một lần nữa jowie!


4
 - (void)zoomMapViewToFitAnnotationsWithExtraZoomToAdjust:(double)extraZoom
{

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

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

   for (id<MKAnnotation> annotation in [self annotations])
  {
      points[i++] = MKMapPointForCoordinate(annotation.coordinate);
   }

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

MKCoordinateRegion r = MKCoordinateRegionForMapRect([poly boundingMapRect]);
r.span.latitudeDelta += extraZoom;
r.span.longitudeDelta += extraZoom;

[self setRegion: r animated:YES];

}

4

Như Abhishek Bedi đã chỉ ra trong một bình luận, Đối với iOS7, cách tốt nhất để làm điều này là:

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

Đối với dự án cá nhân của tôi (trước iOS7) tôi chỉ cần thêm một danh mục trên lớp MKMapView để đóng gói chức năng "vùng hiển thị" cho một hoạt động rất phổ biến: đặt nó để có thể xem tất cả các chú thích hiện được tải trên đối tượng MKMapView ( điều này bao gồm nhiều chân như bạn có thể đã đặt, cũng như vị trí của người dùng). kết quả là thế này:

tập tin .h

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

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


@end

tập tin .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 thức: một phương pháp để đặt 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 được tải trên đối tượng MKMapView và một phương thức khác để đặt nó vào bất kỳ mảng đối tượng nào. Vì vậy, để đặt vùng hiển thị của mapView, mã sẽ đơn giản như sau:

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

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


3

Tất cả các câu trả lời trên trang này đều cho rằng bản đồ chiếm toàn màn hình . Tôi thực sự có một màn hình HUD (tức là các nút nằm rải rác ở trên cùng và dưới cùng) cung cấp thông tin trên bản đồ .. và vì vậy các thuật toán trên trang sẽ hiển thị các chân đúng, nhưng một số trong số chúng sẽ xuất hiện bên dưới các nút hiển thị HUD .

Giải pháp của tôi phóng to bản đồ để hiển thị các chú thích trong một tập hợp con của màn hình và hoạt động với các kích thước màn hình khác nhau (ví dụ 3,5 "so với 4.0", v.v.):

// create a UIView placeholder and throw it on top of the original mapview
// position the UIView to fit the maximum area not hidden by the HUD display buttons
// add an *other* mapview in that uiview, 
// get the MKCoordinateRegion that fits the pins from that fake mapview
// kill the fake mapview and set the region of the original map 
// to that MKCoordinateRegion.

Đây là những gì tôi đã làm trong mã (lưu ý: tôi sử dụng NSConstraintsvới một số phương thức trợ giúp để làm cho mã của tôi hoạt động ở các kích thước màn hình khác nhau .. trong khi mã khá dễ đọc .. câu trả lời của tôi ở đây giải thích điều đó tốt hơn .. về cơ bản là cùng một quy trình làm việc :)

// position smallerMap to fit available space
// don't store this map, it will slow down things if we keep it hidden or even in memory
[@[_smallerMapPlaceholder] mapObjectsApplyingBlock:^(UIView *view) {
    [view removeFromSuperview];
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
    [view setHidden:NO];
    [self.view addSubview:view];
}];

NSDictionary *buttonBindingDict = @{ @"mapPlaceholder": _smallerMapPlaceholder};

NSArray *constraints = [@[@"V:|-225-[mapPlaceholder(>=50)]-176-|",
                          @"|-40-[mapPlaceholder(<=240)]-40-|"
                          ] mapObjectsUsingBlock:^id(NSString *formatString, NSUInteger idx){
                              return [NSLayoutConstraint constraintsWithVisualFormat:formatString options:0 metrics:nil views:buttonBindingDict];
                          }];

[self.view addConstraints:[constraints flattenArray]];
[self.view layoutIfNeeded];

MKMapView *smallerMap = [[MKMapView alloc] initWithFrame:self.smallerMapPlaceholder.frame];
[_smallerMapPlaceholder addSubview:smallerMap];

MKCoordinateRegion regionThatFits = [smallerMap getRegionThatFits:self.mapView.annotations];
[smallerMap removeFromSuperview];
smallerMap = nil;
[_smallerMapPlaceholder setHidden:YES];

[self.mapView setRegion:regionThatFits animated:YES];

đây là mã có được vùng phù hợp:

- (MKCoordinateRegion)getRegionThatFits:(NSArray *)routes {
    MKCoordinateRegion region;
    CLLocationDegrees maxLat = -90.0;
    CLLocationDegrees maxLon = -180.0;
    CLLocationDegrees minLat = 90.0;
    CLLocationDegrees minLon = 180.0;
    for(int idx = 0; idx < routes.count; idx++)
    {
        CLLocation* currentLocation = [routes objectAtIndex:idx];
        if(currentLocation.coordinate.latitude > maxLat)
            maxLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.latitude < minLat)
            minLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.longitude > maxLon)
            maxLon = currentLocation.coordinate.longitude;
        if(currentLocation.coordinate.longitude < minLon)
            minLon = currentLocation.coordinate.longitude;
    }
    region.center.latitude     = (maxLat + minLat) / 2.0;
    region.center.longitude    = (maxLon + minLon) / 2.0;
    region.span.latitudeDelta = 0.01;
    region.span.longitudeDelta = 0.01;

    region.span.latitudeDelta  = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
    region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);

    MKCoordinateRegion regionThatFits = [self regionThatFits:region];
    return regionThatFits;
}

2

Tôi đã thực hiện một chút sửa đổi mã của Rafael cho Danh mục MKMapView.

- (void)zoomToFitMapAnnotations {
    if ([self.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 self.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

    [self setRegion:[self regionThatFits:region] animated:YES];
}

2

Dựa trên các câu trả lời ở trên, bạn có thể sử dụng phương pháp phổ quát để thu phóng bản đồ để phù hợp với tất cả các chú thích và lớp phủ cùng một lúc.

-(MKMapRect)getZoomingRectOnMap:(MKMapView*)map toFitAllOverlays:(BOOL)overlays andAnnotations:(BOOL)annotations includeUserLocation:(BOOL)userLocation {
    if (!map) {
        return MKMapRectNull;
    }

    NSMutableArray* overlaysAndAnnotationsCoordinateArray = [[NSMutableArray alloc]init];        
    if (overlays) {
        for (id <MKOverlay> overlay in map.overlays) {
            MKMapPoint overlayPoint = MKMapPointForCoordinate(overlay.coordinate);
            NSArray* coordinate = @[[NSNumber numberWithDouble:overlayPoint.x], [NSNumber numberWithDouble:overlayPoint.y]];
            [overlaysAndAnnotationsCoordinateArray addObject:coordinate];
        }
    }

    if (annotations) {
        for (id <MKAnnotation> annotation in map.annotations) {
            MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
            NSArray* coordinate = @[[NSNumber numberWithDouble:annotationPoint.x], [NSNumber numberWithDouble:annotationPoint.y]];
            [overlaysAndAnnotationsCoordinateArray addObject:coordinate];
        }
    }

    MKMapRect zoomRect = MKMapRectNull;
    if (userLocation) {
        MKMapPoint annotationPoint = MKMapPointForCoordinate(map.userLocation.coordinate);
        zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
    }

    for (NSArray* coordinate in overlaysAndAnnotationsCoordinateArray) {
        MKMapRect pointRect = MKMapRectMake([coordinate[0] doubleValue], [coordinate[1] doubleValue], 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }

    return zoomRect;
}

Và sau đó:

MKMapRect mapRect = [self getZoomingRectOnMap:mapView toFitAllOverlays:YES andAnnotations:YES includeUserLocation:NO];
[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0) animated:YES];

1

Chỉ chia sẻ những quan sát của tôi về điều này:

Nếu bạn đang sử dụng xCode> 6 với kích thước "được suy ra" cho màn hình (xem "số liệu mô phỏng" trên trình kiểm tra tệp) trong bảng phân cảnh, hãy gọi

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

trong viewDidLoadsẽ dẫn đến một mức độ phóng quá lớn trên iPhone với 4 inch bởi vì cách bố trí cho bản đồ vẫn còn nằm trên kích thước của màn hình rộng hơn từ kịch bản này.

Bạn có thể di chuyển cuộc gọi của bạn showAnnotations...đến viewDidAppear. Sau đó, kích thước của bản đồ đã được điều chỉnh thành màn hình nhỏ hơn của iPhone 4.

Hoặc thay thế giá trị "suy ra" trong trình kiểm tra tệp trong "số liệu mô phỏng" thành iphone 4 inch.


1

Bạn có thể chọn hình dạng bạn muốn hiển thị cùng với Chú thích.

extension MKMapView {
  func setVisibleMapRectToFitAllAnnotations(animated: Bool = true,
                                            shouldIncludeUserAccuracyRange: Bool = true,
                                            shouldIncludeOverlays: Bool = true,
                                            edgePadding: UIEdgeInsets = UIEdgeInsets(top: 35, left: 35, bottom: 35, right: 35)) {
    var mapOverlays = overlays

    if shouldIncludeUserAccuracyRange, let userLocation = userLocation.location {
      let userAccuracyRangeCircle = MKCircle(center: userLocation.coordinate, radius: userLocation.horizontalAccuracy)
      mapOverlays.append(MKOverlayRenderer(overlay: userAccuracyRangeCircle).overlay)
    }

    if shouldIncludeOverlays {
      let annotations = self.annotations.filter { !($0 is MKUserLocation) }
      annotations.forEach { annotation in
        let cirlce = MKCircle(center: annotation.coordinate, radius: 1)
        mapOverlays.append(cirlce)
      }
    }

    let zoomRect = MKMapRect(bounding: mapOverlays)
    setVisibleMapRect(zoomRect, edgePadding: edgePadding, animated: animated)
  }
}

extension MKMapRect {
  init(bounding overlays: [MKOverlay]) {
    self = .null
    overlays.forEach { overlay in
      let rect: MKMapRect = overlay.boundingMapRect
      self = self.union(rect)
    }
  }
}

0

@ "Tôi không chắc liệu đây có phải là do một số yếu tố khác trong quá trình triển khai của mình không, nhưng tôi thấy rằng showAnnotations không thực hiện việc phóng to / thu nhỏ các chú thích như khi thực hiện thủ công, vì vậy tôi đã mắc kẹt với hướng dẫn sử dụng. - Ted Avery 17 tháng 4 lúc 3:35 "

Tôi đã có cùng một vấn đề, nhưng sau đó tôi đã thử thực hiện showAnnotations hai lần (như bên dưới) và vì một số lý do, nó đã hoạt động.

[mapView showAnnotations: yourAnnotationArray hoạt hình: CÓ]; [mapView showAnnotations: yourAnnotationArray hoạt hình: CÓ];


0

Một cách tương thích với iOS 7 là sử dụng như sau. Cuộc gọi đầu tiên showAnnotationđể có được một hình chữ nhật bao gồm tất cả các chú thích. Sau đó tạo và UIEdgeInsetvới một đầu trên của chiều cao pin. Do đó, bạn đảm bảo hiển thị toàn bộ pin trên bản đồ.

[self.mapView showAnnotations:self.mapView.annotations animated:YES];
MKMapRect rect = [self.mapView visibleMapRect];
UIEdgeInsets insets = UIEdgeInsetsMake(pinHeight, 0, 0, 0);
[self.mapView setVisibleMapRect:rect edgePadding:insets animated:YES];

0

Đặt mã này vào mã của bạn cho phù hợp:

  - (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
    {
    id<MKAnnotation> mp = [annotationView annotation];
        MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate] ,250,250);

       [mv setRegion:region animated:YES];

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