एनोटेशन पिंस को फिट करने के लिए एमके मैप देखें?


193

मैं MKMapView का उपयोग कर रहा हूं और 5-10 किलोमीटर क्षेत्र के बारे में नक्शे में कई एनोटेशन पिन जोड़े हैं। जब मैं एप्लिकेशन चलाता हूं तो मेरा नक्शा पूरी दुनिया को दिखाने के लिए ज़ूम आउट करना शुरू कर देता है, मैप को ज़ूम करने का सबसे अच्छा तरीका क्या है ताकि पिन दृश्य को फिट कर सके?

संपादित करें: मेरी प्रारंभिक सोच MKCoordinateRegionMake का उपयोग करना और समन्वय केंद्र, देशांतरDelta और अक्षांशों की गणना करना होगा। मुझे पूरा यकीन है कि यह काम करेगा, लेकिन मैं सिर्फ यह जांचना चाहता था कि मुझे कुछ भी याद नहीं है।

कोड जोड़ा गया, BTW: FGLocation एक ऐसा वर्ग है जो इसके अनुरूप है MKAnnotation, स्थानक 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);
अभिषेक बेदी

1
यह अच्छी तरह से काम करता है, लेकिन कभी-कभी जब मैं (मानचित्र में) ज़ूम करता हूं तो इसे केंद्र करने की कोशिश करें (एक बटन का उपयोग करके जो इस विधि को लागू करता है) यह काम नहीं करता है।
RPM

5
यह नोट करना महत्वपूर्ण है कि showAnnotationsनक्शे में एनोटेशन भी जोड़ता है, भले ही उस स्थान के लिए एनोटेशन पहले से मौजूद हो।
एनेको अलोंसो

@EnekoAlonso इसके removeAnnotations(_ annotations:)तुरंत बाद कॉल करके आप इसके आसपास काम कर सकते हैंshowAnnotations(_ annotations:animated)
Alain Stulz

1
यह भी ध्यान देने योग्य है कि जब showAnnotations एनोटेशन प्रदर्शित करने के लिए क्षेत्र सेट करता है, तो क्षेत्र अभी भी पहलू अनुपात से मेल खाने के लिए समायोजित हो जाता है; और यह अक्सर कुछ एनोटेशन को बाहर कर देगा। यह भी ध्यान दें कि showAnnotations यहाँ प्रस्तुत एकमात्र सही समाधान है; कोई अन्य उत्तर भी अंतर्राष्ट्रीय तिथि रेखा में फैले एनोटेशन को संभालने का प्रयास नहीं करता है।
गॉर्डन कबूतर

335

यह वही है जो मैंने यहां पाया है जो मेरे लिए काम करता है:

(संपादित करें: मैंने यह सुनिश्चित करने के लिए समाधान को अपडेट कर लिया है कि मीका का सुझाव 0.1% तक बढ़ सकता है, यह सुनिश्चित करने के लिए कि यह रूट अंत में असीम रूप से छोटा नहीं है!)

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

 

आप इसके साथ पहली पंक्ति को प्रतिस्थापित करके भी उपयोगकर्ता लिंक पिन शामिल करने के लिए इसे अपडेट कर सकते हैं:

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

4
वास्तव में अच्छा लगा। आपको जाँच करने की आवश्यकता नहीं है, हालांकि नल। MKMapRectUnion यह आपके लिए करता है। डॉक्स से: "यदि या तो आयत शून्य है, तो यह विधि अन्य आयत को लौटा देती है।"
फेलिक्स लामोरौक्स

37
बहुत अच्छा समाधान !!! यहाँ कुछ गद्दी जोड़ने के लिए एक अतिरिक्त हल्का स्पर्श है: डबल इनसेट = -zoomRect.size. उपलब्धता * 0.1; [self.mapView setVanishMapRect: MKMapRectInset (zoomRect, इनसेट, इनसेट) एनिमेटेड: YES];
क्रेग बी

1
बहुत बढ़िया! संभावित जोड़: यदि आप 'वर्तमान स्थान एनोटेशन' को बाहर करना चाहते हैं, तो केवल लूप के लिए एक स्टेटमेंट जोड़ें: if (([एनोटेशन isKindOfClass: [MKUserLocation class]])) {// यहाँ सामग्री
लोड

2
पैडिंग के लिए @ क्रैगब समाधान उत्कृष्ट है, लेकिन यह अच्छी तरह से काम नहीं करता है, जब पथ ऊर्ध्वाधर है, उदाहरण के लिए दक्षिण से उत्तर की ओर गति, इस उपयोग को ठीक करने के लिए डबल इनसेट = MIN (-zoomRect.size. उपलब्धता * 0.1 -zoomRect .size। ऊंचाई * 0.1);
फरहाद मालेकपुर

1
पैडिंग के साथ वृद्धि: डबल इनसेटविद = -zoomRect.size. उपलब्धता * 0.2; double insetHeight = -zoomRect.size.height * 0.2; MKMapRect insetRect = MKMapRectInset (ZoomRect, insetWidth, insetHeight); फिर इस नए इन्सर्ट का उपयोग करें
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मैनुअल कार्यान्वयन के रूप में एनोटेशन के एक ज़ूम / फिट के करीब नहीं करता है, इसलिए मैं मैनुअल एक के साथ फंस गया हूं।
टेड एवरी

1
एक के एक अंश से कैमरों की ऊंचाई को गुणा करने की कोशिश करें, जैसे mapView.camera.altitude * = .85; करीब से देखने के लिए
रयान बर्ग

मैंने इसे वर्तमान दृश्यमान मानचित्र क्षेत्र के बाहर एनोटेशन चुनने के लिए भी उपयोगी पाया है। डिफ़ॉल्ट रूप से, MapView गैर-दृश्य एनोटेशन का चयन नहीं करता है। SelectAnnotation को कॉल करने से पहले अपने गैर-दृश्यमान एनोटेशन (ओं) के एक सरणी के साथ शोऑनोटेशन को कॉल करें, और मैप को अपने देखने योग्य क्षेत्र को अपडेट करना चाहिए।
मंडिसा डब्ल्यू

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

174.13666611126533: 46.969995730376894 - देशांतर: -109.2494943434474 ▿ 1: CLLocationCoordinate2D -: - अक्षांश देशांतर 63.23212154333072 -: ▿ 2 तत्वों ▿ 0: अक्षांश CLLocationCoordinate2D लिए काम नहीं करते
Olexiy Pyvovarov

23

स्विफ्ट उपयोग में

mapView.showAnnotations(annotationArray, animated: true)

ऑब्जेक्टिव सी में

[mapView showAnnotations:annotationArray animated:YES];

2
यदि एनोटेशन पहले से ही मैप व्यू पर सेट किए गए हैं, तो आप उन्हें सीधे इसके साथ संदर्भित कर सकते हैं:mapView.showAnnotations(mapView.annotations, animated: true)
जस्टिन वैलेली

14

मैंने राफेल मोरेरा के जवाब को बदल दिया है। इसका श्रेय उन्हें जाता है। आप में से जो स्विफ्ट संस्करण की तलाश कर रहे हैं, उनके लिए यहां कोड है:

 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

स्विफ्ट 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 आपके सुझाए गए संपादन को अस्वीकार कर दिया गया है, यदि आप स्विफ्ट 4.2 के लिए एक नया उत्तर प्रदान करना चाहते हैं, तो स्वतंत्र महसूस करें, लेकिन इसे एक उत्तर के रूप में जोड़ें, न कि किसी अन्य उपयोगकर्ता पोस्ट में संपादित करके।
निक

13

@ jowie का समाधान बढ़िया काम करता है। एक कैच, अगर एक मैप में केवल एक एनोटेशन है तो आप पूरी तरह से ज़ूम आउट मैप के साथ समाप्त हो जाएंगे। मैंने यह सुनिश्चित करने के लिए कि सेट ज़ूम करने के लिए कुछ करने के लिए रेक्ट मेक आकार में 0.1 जोड़ दिया।

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)

उदाहरण के लिए (स्विफ्ट 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 सिम्युलेटर का उपयोग करके परीक्षण कर रहा था। उदाहरण कोड setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(100, 100, 100, 100), animated: true):। एक नोट के रूप में, यह कोड स्विफ्ट 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);

टिप्पणी से - अभिषेक बेदी

आप बस फोन करें:

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

केवल संदर्भ के लिए, NS_AVAILABLE पाठ वहाँ था क्योंकि जनवरी 2011 में, डिवाइस पर iOS 7 होने की संभावना सुपर नहीं थी, और NS_AVAILABLE ने एप्लिकेशन को बिल्ड विफलता या क्रैश से सुरक्षित रखा।
मैथ्यू फ्रेडरिक

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

जैसा कि अभिषेक बेदी ने एक टिप्पणी में बताया है, 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 वर्ग पर एक श्रेणी जोड़ी है: यह सेट करना MK MKMap उदाहरण पर सभी वर्तमान में लोड किए गए एनोटेशन को देखने में सक्षम हो सकता है इसमें उतने पिन शामिल हैं जितना आपने रखा होगा, साथ ही उपयोगकर्ता का स्थान भी)। परिणाम यह था:

.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 प्रदर्शन है कि नक्शे के ontop जानकारी दे (यानी बटन ऊपर और नीचे बिखरे हुए) .. और इतने पृष्ठ पर एल्गोरिदम पिंस सब ठीक प्रदर्शित करेगा, लेकिन उनमें से कुछ दिखाई देगा के तहत HUD प्रदर्शन बटन ।

मेरा समाधान स्क्रीन के सबसेट में एनोटेशन प्रदर्शित करने के लिए मैप को ज़ूम करता है और विभिन्न स्क्रीन साइज़ (यानी 3.5 "बनाम 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 का उपयोग कर रहे हैं (फाइल इंस्पेक्टर पर "सिम्युलेटेड मैट्रिक्स" देखें)

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

, viewDidLoadआईफ़ोन पर 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

@ "मुझे यकीन नहीं है कि यह मेरे कार्यान्वयन में कुछ अन्य कारकों की वजह से है, लेकिन मुझे लगता है कि showAnnotations मैनुअल कार्यान्वयन के रूप में एनोटेशन के ज़ूम / फिट के करीब नहीं करता है, इसलिए मैं इसके साथ फंस गया हूं मैनुअल एक। - टेड एवरी अप्रैल 17 को 0:35 पर "

मुझे भी यही समस्या थी, लेकिन फिर मैंने दो बार (नीचे की तरह) शोऑनोटेशन करने की कोशिश की, और किसी कारण से, यह काम कर गया।

[mapView showAnnotations: yourAnnotationArray एनिमेटेड: YES]; [mapView showAnnotations: 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];

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.