กำลังซูม MKMapView ให้พอดีกับหมุดคำอธิบายประกอบ?


193

ฉันใช้ MKMapView และเพิ่มหมุดคำอธิบายประกอบลงในแผนที่ประมาณ 5-10 กิโลเมตร เมื่อฉันเรียกใช้แอพพลิเคชั่นแผนที่ของฉันเริ่มซูมออกเพื่อแสดงให้โลกทั้งโลกเห็นว่าวิธีที่ดีที่สุดในการซูมแผนที่คืออะไร

แก้ไข: ความคิดเริ่มต้นของฉันคือการใช้ MKCoordinateRegionMake และคำนวณศูนย์ประสานงานลองจิจูดลองจิจูดและละติจูดเดลตาจากคำอธิบายประกอบของฉัน ฉันค่อนข้างมั่นใจว่ามันจะใช้งานได้ แต่ฉันแค่ต้องการตรวจสอบว่าฉันไม่พลาดอะไรที่ชัดเจน

เพิ่มรหัส BTW: FGLocation เป็นคลาสที่สอดคล้องกับMKAnnotationlocationFake เป็นNSMutableArrayวัตถุเหล่านี้ ความคิดเห็นยินดีต้อนรับเสมอ ....

- (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
iOS 7 หมายเหตุ: รายการใหม่คำอธิบาย: ภาพเคลื่อนไหว:วิธีการสามารถช่วยคุณหลีกเลี่ยงการคำนวณภูมิภาคด้วยตนเอง

คำตอบ:


123

คุณทำให้ถูกต้อง

MKCoordinateRegionMakeค้นหาสูงสุดและต่ำสุดละติจูดและลองจิจูดของคุณใช้บางคณิตศาสตร์ที่เรียบง่ายและการใช้งาน

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

5
สิ่งสำคัญคือต้องทราบว่าshowAnnotationsจะเพิ่มคำอธิบายประกอบลงในแผนที่แม้ว่าจะมีคำอธิบายประกอบสำหรับตำแหน่งนั้นอยู่แล้ว
Eneko Alonso

@EnekoAlonso คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยการโทรremoveAnnotations(_ annotations:)ทันทีหลังจากshowAnnotations(_ annotations:animated)
Alain Stulz

1
สิ่งที่ควรสังเกตคือในขณะที่ showAnnotations ตั้งค่าภูมิภาคเพื่อแสดงคำอธิบายประกอบ แต่พื้นที่ยังคงได้รับการปรับให้เข้ากับอัตราส่วนภาพ และสิ่งนี้มักจะไม่รวมคำอธิบายประกอบบางรายการ นอกจากนี้โปรดทราบว่า showAnnotations เป็นทางออกที่ถูกต้องเพียงข้อเดียว ไม่มีคำตอบอื่นใดแม้แต่พยายามจัดการคำอธิบายประกอบซึ่งประกอบไปด้วยบรรทัดวันที่สากล
Gordon Dove

335

นี่คือสิ่งที่ฉันพบที่นี่ที่ทำงานสำหรับฉัน:

(แก้ไข: ฉันได้อัปเดตวิธีแก้ปัญหาโดยใช้คำแนะนำของ @ Micah เพื่อเพิ่ม pointRect 0.1 เพื่อให้แน่ใจว่า rect ไม่ได้มีขนาดเล็กมาก!)

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

 

คุณสามารถอัปเดตสิ่งนี้เพื่อรวมพิน userLocation โดยแทนที่บรรทัดแรกด้วย:

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

4
ดีมาก คุณไม่จำเป็นต้องตรวจสอบว่าไม่มี MKMapRectUnion ทำสิ่งนี้ให้คุณ จากเอกสาร: "ถ้าสี่เหลี่ยมผืนผ้าใดเป็นโมฆะวิธีนี้จะส่งกลับสี่เหลี่ยมผืนผ้าอื่น"
Felix Lamouroux

37
ทางออกที่ดีมาก !!! ต่อไปนี้เป็นความพิเศษเล็กน้อยในการเพิ่มช่องว่าง: double inset = -zoomRect.size.width * 0.1; [self.mapView setVisibleMapRect: MKMapRectInset (zoomRect, สิ่งที่ใส่เข้าไป, ภาพประกอบ) เคลื่อนไหว: YES];
Craig B

1
! น่ากลัว การเพิ่มที่เป็นไปได้: หากคุณต้องการแยก 'หมายเหตุประกอบตำแหน่งปัจจุบัน' เพียงเพิ่มคำสั่ง if ในห่วง for: if (! [คำอธิบายประกอบ isKindOfClass: [MKUserLocation class]] {// ทำสิ่งที่นี่}
kgaidis

2
@CraigB เป็นวิธีแก้ปัญหาการขยายตัวที่ยอดเยี่ยม แต่มันทำงานได้ไม่ดีเมื่อเส้นทางอยู่ในแนวตั้งเช่นการเคลื่อนไหวจากทางทิศใต้ไปทางทิศเหนือเพื่อแก้ไขการใช้ double inset = MIN (-zoomRect.size.width * 0.1, -zoomRect.size ความสูง * 0.1);
Farhad Malekpour

1
การปรับปรุงด้วยการขยาย: double insetWidth = -zoomRect.size.width * 0.2; double insetHeight = -zoomRect.size.height * 0.2; MKMapRect insetRect = MKMapRectInset (zoomRect, insetWidth, insetHeight); จากนั้นใช้ insertRect ใหม่นี้
dulgan

121

Apple ได้เพิ่มวิธีการใหม่สำหรับ IOS 7 เพื่อทำให้ชีวิตง่ายขึ้นเล็กน้อย

[mapView showAnnotations:yourAnnotationArray animated:YES];

คุณสามารถดึงจากอาเรย์ที่เก็บไว้ในมุมมองแผนที่ได้อย่างง่ายดาย:

yourAnnotationArray = mapView.annotations;

และปรับกล้องอย่างรวดเร็วด้วย!

mapView.camera.altitude *= 1.4;

สิ่งนี้จะไม่ทำงานจนกว่าผู้ใช้จะติดตั้ง iOS 7+ หรือ OS X 10.9+ ตรวจสอบภาพเคลื่อนไหวที่กำหนดเองที่นี่


ฉันไม่แน่ใจว่านี่เป็นเพราะปัจจัยอื่น ๆ ในการใช้งานของฉันหรือไม่ แต่ฉันพบว่าshowAnnotationsมันไม่ได้เป็นการซูม / ขนาดพอดีของคำอธิบายประกอบเหมือนกับการใช้งานด้วยตนเองดังนั้นฉันจึงติดอยู่กับคู่มือ
Ted Avery

1
ลองคูณความสูงของกล้องด้วยเศษส่วนของเศษส่วนเช่น mapView.camera.altitude * = .85; สำหรับพอร์ตวิวที่ใกล้กว่า
Ryan Berg

ฉันพบว่ามีประโยชน์สำหรับการเลือกคำอธิบายประกอบนอกพื้นที่แผนที่ปัจจุบันที่มองเห็นได้ ตามค่าเริ่มต้น MapView จะไม่เลือกคำอธิบายประกอบที่มองไม่เห็น โทร showAnnotations พร้อมอาร์เรย์ของคำอธิบายประกอบที่ไม่สามารถมองเห็นได้ของคุณก่อนที่จะโทรเลือกคำอธิบายประกอบและแผนที่ควรอัปเดตพื้นที่ที่สามารถดูได้
MandisaW

42

ฉันใช้รหัสนี้และทำงานได้ดีสำหรับฉัน:

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

ไม่ทำงานสำหรับ: ▿ 2 องค์ประกอบ▿ 0: CLLocationCoordinate2D - ละติจูด: 46.969995730376894 - ลองจิจูด: -109.2494943434474 ▿ 1: CLLocationCoordinate2D - ละติจูด: 63.23212154333072 - ลองจิจูด: 174.13666611126533
Olexiy Pyvovarov

23

ในการใช้งานอย่างรวดเร็ว

mapView.showAnnotations(annotationArray, animated: true)

ในวัตถุประสงค์ c

[mapView showAnnotations:annotationArray animated:YES];

2
หากคำอธิบายประกอบได้ถูกกำหนดไว้แล้วบน mapView คุณสามารถอ้างอิงได้โดยตรงกับ:mapView.showAnnotations(mapView.annotations, animated: true)
Justin Vallely

14

ฉันแปลงคำตอบของ Rafael Moreira แล้ว เครดิตไปกับเขา สำหรับผู้ที่กำลังมองหาเวอร์ชั่น Swift นี่คือรหัส:

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

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 การแก้ไขที่คุณแนะนำถูกปฏิเสธหากคุณต้องการให้คำตอบใหม่สำหรับ Swift 4.2 แต่อย่าลังเลที่จะเพิ่มคำตอบไม่ใช่เพิ่มโดยการแก้ไขในโพสต์ผู้ใช้รายอื่น
Nick

13

โซลูชันของ @ jowie ใช้งานได้ดี หนึ่งจับถ้าแผนที่มีเพียงหนึ่งคำอธิบายประกอบคุณจะจบลงด้วยแผนที่ซูมออกอย่างเต็มที่ ฉันเพิ่ม 0.1 ไปยังขนาด make rect เพื่อให้แน่ใจว่า setVisibleMapRect มีบางอย่างที่จะซูม

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

12

หากคุณกำลังมองหาiOS 8 ขึ้นไปวิธีที่ง่ายที่สุดในการทำคือตั้งค่าvar layoutMargins: UIEdgeInsets { get set }มุมมองแผนที่ของคุณก่อนโทรfunc showAnnotations(annotations: [MKAnnotation], animated: Bool)

ตัวอย่างเช่น (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

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

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

ฉันจัดการเพื่อให้ได้ผลลัพธ์ที่ดีขึ้นโดยการเปลี่ยนUIEdgeInsetsMakeพารามิเตอร์ค่าระหว่าง 30 ถึง 100 นั้นดีสำหรับฉัน ฉันกำลังทดสอบโดยใช้ iPhone SE i) S 10.2 Simulator รหัสตัวอย่าง: setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(100, 100, 100, 100), animated: true). ตามที่ระบุไว้รหัสนี้ใช้งานได้ใน Swift 3 และ XCode 8.2.1
nyxee

8

เพิ่มนี่ถ้าวนรอบภายในสำหรับวนซ้ำเพื่อแยกพินตำแหน่งผู้ใช้ออกจากวิธีนี้ (จำเป็นในกรณีของฉันและอาจเป็นอย่างอื่น)

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

//Code Here...

}

8

สำหรับ iOS 7 ขึ้นไป (การอ้างอิง 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

คุณเพียงแค่โทร:

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

เพื่อการอ้างอิงเท่านั้นข้อความ NS_AVAILABLE มีอยู่ในนั้นเพราะในเดือนมกราคม 2554 การมี iOS 7 บนอุปกรณ์ไม่น่าจะเป็นไปได้มากและ NS_AVAILABLE ได้ป้องกันแอปจากความล้มเหลวในการสร้างหรือความล้มเหลว
Matthew Frederick

5

ในสวิฟท์

    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)

// แก้ไขเพื่อความรวดเร็ว 5


4

ขอบคุณ jowie ฉันได้อัปเดตหมวดหมู่เก่าของฉันเป็นโซลูชันที่หรูหรายิ่งขึ้น การแชร์เสร็จสมบูรณ์เกือบลอกและวางโซลูชันที่พร้อม

MKMapView + AnnotationsRegion.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 + AnnotationsRegion.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

หวังว่ามันจะช่วยให้ใครบางคนและขอบคุณอีกครั้ง 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

Abhishek Bedi ชี้ให้เห็นในความคิดเห็นสำหรับ iOS7 ส่งต่อวิธีที่ดีที่สุดในการทำเช่นนี้คือ:

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

สำหรับโครงการส่วนตัวของฉัน (ก่อนหน้า iOS7) ฉันเพิ่งเพิ่มหมวดหมู่ในคลาส 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]; 

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


3

คำตอบทั้งหมดในหน้านี้ คิดว่าแผนที่ตรงแบบเต็มหน้าจอ จริง ๆ แล้วฉันมีการแสดง HUD (เช่นปุ่มกระจายอยู่ที่ด้านบนและด้านล่าง) ที่ให้ข้อมูลบนแผนที่ .. และอัลกอริทึมบนหน้าจะแสดงหมุดได้ถูกต้อง แต่บางส่วนจะปรากฏภายใต้ปุ่มการแสดงผล HUD .

โซลูชันของฉันซูมแผนที่เพื่อแสดงคำอธิบายประกอบในชุดย่อยของหน้าจอและใช้งานได้ขนาดหน้าจอที่แตกต่างกัน (เช่น 3.5 "vs 4.0" ฯลฯ ):

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

นี่คือสิ่งที่ฉันทำในรหัส (หมายเหตุ: ฉันใช้NSConstraintsกับวิธีการช่วยเหลือบางอย่างเพื่อให้รหัสของฉันทำงานในขนาดหน้าจอที่แตกต่างกัน .. ในขณะที่รหัสค่อนข้างอ่านได้ .. คำตอบของฉันที่นี่อธิบายได้ดีขึ้น ..

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

นี่คือรหัสที่ได้รับภูมิภาคที่เหมาะกับ:

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

ฉันได้ทำการปรับเปลี่ยนรหัสราฟาเอลเล็กน้อยสำหรับประเภท 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

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

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

แล้ว:

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

เพียงแบ่งปันข้อสังเกตของฉันเกี่ยวกับสิ่งนี้:

หากคุณใช้ xCode> 6 ที่มีขนาด "inferred" สำหรับหน้าจอ (ดูที่ "ตัวชี้วัดจำลอง" ในตัวตรวจสอบไฟล์) ในกระดานเรื่องราวการโทร

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

ใน viewDidLoadจะส่งผลให้ระดับการซูมขนาดใหญ่เกินไปบน iPhone 4 นิ้วเพราะรูปแบบสำหรับแผนที่จะยังคงอยู่กับขนาดของหน้าจอที่กว้างขึ้นจากกระดานเรื่องราว

คุณสามารถย้ายการเรียกร้องให้ไปshowAnnotations... viewDidAppearจากนั้นปรับขนาดของแผนที่เป็นหน้าจอขนาดเล็กของ iPhone 4

หรือเปลี่ยนค่า "อนุมาน" ในตัวตรวจสอบไฟล์ภายใต้ "ตัวชี้วัดจำลอง" เป็น iphone 4 นิ้ว


1

คุณสามารถเลือกรูปร่างที่คุณต้องการแสดงพร้อมกับคำอธิบายประกอบ

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

@ "ฉันไม่แน่ใจว่านี่เป็นเพราะปัจจัยอื่น ๆ ในการนำไปใช้ของฉันหรือไม่ แต่ฉันพบว่าคำอธิบายประกอบนั้นไม่ได้ทำให้การย่อ / ขยายพอดีกับคำอธิบายประกอบเหมือนกับการใช้งานด้วยตนเองฉันเลยติดอยู่กับ คู่มือหนึ่ง - Ted Avery 17 เมษายนเวลา 0:35 "

ฉันมีปัญหาเดียวกัน แต่แล้วฉันก็ลองทำข้อสังเกตสองครั้ง (เหมือนด้านล่าง) และด้วยเหตุผลบางอย่างมันใช้ได้ผล

[mapView แสดงคำอธิบายประกอบ: yourAnnotationArray เคลื่อนไหว: YES]; [mapView แสดงคำอธิบายประกอบ: yourAnnotationArray เคลื่อนไหว: YES];


0

วิธีที่เข้ากันได้กับ iOS 7 คือการใช้สิ่งต่อไปนี้ การโทรครั้งแรกshowAnnotationเพื่อรับสี่เหลี่ยมผืนผ้าพร้อมคำอธิบายประกอบทั้งหมด หลังจากนั้นสร้างและUIEdgeInsetมีสิ่งที่ใส่เข้าไปด้านบนของความสูงของพิน ดังนั้นคุณต้องแสดงหมุดทั้งหมดบนแผนที่

[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

ใส่รหัสนี้ในรหัสของคุณ:

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

       [mv setRegion:region animated:YES];

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