複数の注釈を一度に表示するためのMKMapViewの配置


92

MKMapViewに追加したい注釈がいくつかあります(0からnの項目があり、nは通常約5です)。注釈を細かく追加できますが、画面上のすべての注釈に一度に収まるようにマップのサイズを変更したいのですが、その方法がわかりません。

私は見てきました-regionThatFits:が、どうすればいいのかよくわかりません。私はこれまでに得たものを示すためにいくつかのコードを投稿します。これは一般的には簡単な作業だと思いますが、今のところMapKitに少し圧倒されています。

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{

location = newLocation.coordinate;
//One location is obtained.. just zoom to that location

MKCoordinateRegion region;
region.center = location;

//Set Zoom level using Span
MKCoordinateSpan span;
span.latitudeDelta = 0.015;
span.longitudeDelta = 0.015;
region.span = span;
// Set the region here... but I want this to be a dynamic size
// Obviously this should be set after I've added my annotations
[mapView setRegion:region animated:YES];

// Test data, using these as annotations for now
NSArray *arr = [NSArray arrayWithObjects:@"one", @"two", @"three", @"four", nil];
float ex = 0.01;
for (NSString *s in arr) {
    JBAnnotation *placemark = [[JBAnnotation alloc] initWithLat:(location.latitude + ex) lon:location.longitude];
    [mapView addAnnotation:placemark];
    ex = ex + 0.005;
}
    // What do I do here?
    [mapView setRegion:[mapView regionThatFits:region] animated:YES];
}

これはすべて、位置情報の更新を受け取ったときに発生します...これが適切な場所かどうかはわかりません。そうでない場合、どこがより良い場所でしょうか?-viewDidLoad

前もって感謝します。

回答:



137

リンクジムで掲示さは今死んでいるが、私は(私はどこかをブックマークしていた)のコードを見つけることができました。お役に立てれば。

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

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

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

    for(id<MKAnnotation> annotation in mapView.annotations) { 
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude); 
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude); 
        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude); 
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude); 
    } 

    MKCoordinateRegion region; 
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5; 
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;      

    // Add a little extra space on the sides
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; 

    region = [mapView regionThatFits:region]; 
    [mapView setRegion:region animated:YES]; 
}

14
私はあなたにキスすることができました。これで時間を大幅に節約できました。上記に1つの場所を処理するコードを追加しました。少し身近になりました。コメントはコードをかき立てる傾向があるので、それを応答として投稿します。
マイケルリード

どうもありがとうございました。これをのサブクラスに追加し、メソッドをMKMapViewに変更しました- (void) zoomToFitAnnotations:(BOOL)animated。完璧に動作します!
simonbs 2012

1
それは非常にうまく機能しています。また、それは便利です。ズームアウトまたはズームインの値を変更できます。so region.span.latitudeDelta = fabs(topLeftCoord.latitude-bottomRightCoord.latitude)* 1.1; ///値を変更します。値を増やすと:ズームアウト........値を減らすと:ズームインの例:region.span.latitudeDelta = fabs(topLeftCoord.latitude-bottomRightCoord.latitude)* 4.1;
Erhan Demirci 2013

1
@ MR.Mustafa:その働き、素晴らしい!しかし、問題を解決することで十分だと思います。それで、誰かが私にそれがどのように機能するかを説明してください。またはリンクを介して。ばかげたら申し訳ありませんが、初心者です。Plsサポート。ありがとう
Siddarth Hailstorm 2013

1
@Mustafa ...ありがとうございます。
Vvk 2015年

133

なぜそんなに複雑なのですか?

MKCoordinateRegion coordinateRegionForCoordinates(CLLocationCoordinate2D *coords, NSUInteger coordCount) {
    MKMapRect r = MKMapRectNull;
    for (NSUInteger i=0; i < coordCount; ++i) {
        MKMapPoint p = MKMapPointForCoordinate(coords[i]);
        r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
    }
    return MKCoordinateRegionForMapRect(r);
}

6
これは、投稿された代替案よりもはるかにシンプル、クリーン、そして簡単です。実際、MKCoordinateRegionに変換する必要がないため、これをさらに簡略化できます。ここで作成するMKMapRectを使用してMKMapViewでsetVisibleMapRect:を呼び出すだけです。
lensovet 2013年

2
注釈がマップの上部に貼り付いて表示されない場合があります。MKCoordinateRegionが作成された後、ズームを拡大するための最良のアプローチに関する入力はありますか?
カイルC

3
@KyleC[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(20.0f, 20.0f, 20.0f, 20.0f) animated:animated];
ユーザー

どのようにCLLocationCoordinate2D *coordsアレイを作成しますか?使用してmalloc()
Hlung 2014

3
@KyleC。r基本的に20%ズームアウトする前にこれを追加しましたCGFloat zoomOutPercent = 0.2f; r = MKMapRectMake(r.origin.x-r.size.width*zoomOutPercent, r.origin.y-r.size.height*zoomOutPercent, r.size.width*(1+zoomOutPercent*2), r.size.height*(1+zoomOutPercent*2));
Loozie

44

ポイントアノテーションと現在の場所を含む領域にズームアウト(またはズームイン)するために、これと同様のことを行いました。アノテーションをループすることでこれを拡張できます。

基本的な手順は次のとおりです。

  • 最小緯度/経度を計算します
  • 最大緯度/経度を計算します
  • これら2つのポイントのCLLocationオブジェクトを作成します
  • ポイント間の距離を計算する
  • ポイント間の中心点と度に変換された距離を使用して領域を作成します
  • MapViewにリージョンを渡して調整します
  • 調整された領域を使用してMapView領域を設定する
    -(IBAction)zoomOut:(id)sender {

        CLLocationCoordinate2D southWest = _newLocation.coordinate;
        CLLocationCoordinate2D northEast = southWest;

        southWest.latitude = MIN(southWest.latitude, _annotation.coordinate.latitude);
        southWest.longitude = MIN(southWest.longitude, _annotation.coordinate.longitude);

        northEast.latitude = MAX(northEast.latitude, _annotation.coordinate.latitude);
        northEast.longitude = MAX(northEast.longitude, _annotation.coordinate.longitude);

        CLLocation *locSouthWest = [[CLLocation alloc] initWithLatitude:southWest.latitude longitude:southWest.longitude];
        CLLocation *locNorthEast = [[CLLocation alloc] initWithLatitude:northEast.latitude longitude:northEast.longitude];

        // This is a diag distance (if you wanted tighter you could do NE-NW or NE-SE)
        CLLocationDistance meters = [locSouthWest getDistanceFrom:locNorthEast];

        MKCoordinateRegion region;
        region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0;
        region.center.longitude = (southWest.longitude + northEast.longitude) / 2.0;
        region.span.latitudeDelta = meters / 111319.5;
        region.span.longitudeDelta = 0.0;

        _savedRegion = [_mapView regionThatFits:region];
        [_mapView setRegion:_savedRegion animated:YES];

        [locSouthWest release];
        [locNorthEast release];
    }

これは進むべき道のようです。ありがとう!
jbrennan 2009

1
誰かがまだこのようにしたい場合に備えてgist.github.comMKCoordinateRegionMake / 1599700を使用してこれを機能させることができました。
チャクリット

region.center.latitude =(southWest.latitude + northEast.latitude)/ 2.0; それをありがとう
トニー

これは子午線の両側のポイントで機能しますか?赤道?
エリオット

1
このコードは、場所に同様のy値がある場合、場所を画面外に配置します。例、(50、-4)と(100、-3)の2つの位置を表示すると、マップがズームしすぎて、座標が画面の左側と右側から外れます。
ユーザー

21

別の答えがあります。私は、ズームツーフィットアルゴリズムを自分で実装するつもりでしたが、私はAppleがいることを考え出ししなければならない、我々はそんなに作業をせずに何を望むかを行うための方法を持っています。API docoを使用すると、MKPolygonを使用して必要なことを実行できることがすぐにわかりました。

/* this simply adds a single pin and zooms in on it nicely */
- (void) zoomToAnnotation:(MapAnnotation*)annotation {
    MKCoordinateSpan span = {0.027, 0.027};
    MKCoordinateRegion region = {[annotation coordinate], span};
    [mapView setRegion:region animated:YES];
}

/* This returns a rectangle bounding all of the pins within the supplied
   array */
- (MKMapRect) getMapRectUsingAnnotations:(NSArray*)theAnnotations {
    MKMapPoint points[[theAnnotations count]];

    for (int i = 0; i < [theAnnotations count]; i++) {
        MapAnnotation *annotation = [theAnnotations objectAtIndex:i];
        points[i] = MKMapPointForCoordinate(annotation.coordinate);
    }

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

    return [poly boundingMapRect];
}

/* this adds the provided annotation to the mapview object, zooming 
   as appropriate */
- (void) addMapAnnotationToMapView:(MapAnnotation*)annotation {
    if ([annotations count] == 1) {
        // If there is only one annotation then zoom into it.
        [self zoomToAnnotation:annotation];
    } else {
        // If there are several, then the default behaviour is to show all of them
        //
        MKCoordinateRegion region = MKCoordinateRegionForMapRect([self getMapRectUsingAnnotations:annotations]);

        if (region.span.latitudeDelta < 0.027) {
            region.span.latitudeDelta = 0.027;
        }

        if (region.span.longitudeDelta < 0.027) {
            region.span.longitudeDelta = 0.027;
        }
        [mapView setRegion:region];
    }

    [mapView addAnnotation:annotation];
    [mapView selectAnnotation:annotation animated:YES];
}

お役に立てれば。


問題はありません。あなたが進んでそれに費やす時間があるなら、通常はより良い方法があります。
PKCLsoft 2012

これはピンを画面の端に少し近すぎます。annotationsRegion.span.latitudeDelta = annotationsRegion.span.latitudeDelta * kEventMapDetailBorderFactor;を追加してみてください。setRegionの直前。
Adam Eberbach、

あなたは正しい@AdamEberbachですが、使用できない定数がクリップに含まれているようです。ピンの周りに「素敵な」境界を提供する値を見つけましたか?
PKCLsoft 2013年

iOS7で新しいshowAnnotationsメソッドを使用することに関する以下のコードコマンダーの答えは、このコードはよりクールですが、実際にはうまく機能する素晴らしいマージンを追加します。
James Toomey 2014

14

この方法でもできます。

// Position the map so that all overlays and annotations are visible on screen.
MKMapRect regionToDisplay = [self mapRectForAnnotations:annotationsToDisplay];
if (!MKMapRectIsNull(regionToDisplay)) myMapView.visibleMapRect = regionToDisplay;

- (MKMapRect) mapRectForAnnotations:(NSArray*)annotationsArray
{
    MKMapRect mapRect = MKMapRectNull;

    //annotations is an array with all the annotations I want to display on the map
    for (id<MKAnnotation> annotation in annotations) { 

        MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);

        if (MKMapRectIsNull(mapRect)) 
        {
            mapRect = pointRect;
        } else 
        {
            mapRect = MKMapRectUnion(mapRect, pointRect);
        }
    }

     return mapRect;
}

13

皆からの情報と提案に基づいて、私は以下を思いつきました。貢献してくれたこのディスカッションのみんなに感謝します:)これはmapViewを含むビューControllerに行きます。

- (void)zoomToFitMapAnnotations { 

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

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

//build array of annotation points
for (id<MKAnnotation> annotation in [self.mapView annotations])
        points[i++] = MKMapPointForCoordinate(annotation.coordinate);

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

[self.mapView setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect]) animated:YES]; 
}

これはより多くの賛成票を獲得するはずです。非常に正確で要領を得ています。
Natasha

5

私の場合、CLLocationオブジェクトから始めて、それぞれに注釈を作成しています。
2つの注釈を配置するだけでよいので、ポイントの配列を構築する簡単な方法がありますが、CLLocationのセットを指定して任意の長さの配列を構築するように簡単に拡張できます。

これが私の実装です(MKMapPointsを作成する必要はありません)。

//start with a couple of locations
CLLocation *storeLocation = store.address.location.clLocation;
CLLocation *userLocation = [LBLocationController sharedController].currentLocation;

//build an array of points however you want
CLLocationCoordinate2D points[2] = {storeLocation.coordinate, userLocation.coordinate};

//the magic part
MKPolygon *poly = [MKPolygon polygonWithCoordinates:points count:2];
[self.mapView setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect])];

5

Swift、ポリゴン、およびいくつかの追加のパディングを使用して、以下を使用しました:

func zoomToFit() {
    var allLocations:[CLLocationCoordinate2D] = [
        CLLocationCoordinate2D(latitude: 32.768805, longitude: -117.167119),
        CLLocationCoordinate2D(latitude: 32.770480, longitude: -117.148385),
        CLLocationCoordinate2D(latitude: 32.869675, longitude: -117.212929)
    ]

    var poly:MKPolygon = MKPolygon(coordinates: &allLocations, count: allLocations.count)

    self.mapView.setVisibleMapRect(poly.boundingMapRect, edgePadding: UIEdgeInsetsMake(40.0, 40.0, 40.0, 40.0), animated: false)
}


setVisibleMapRect(...)。私は数学を自分でやっていた...
CodeReaper 2016

3

「MKMapView」には、iOS 7で使用できる新しいメソッドがあります

宣言

迅速

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

OBJECTIVE-C

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

パラメーター

アノテーションマップに表示するアノテーション。アニメーション化マップ領域の変更をアニメーション化する場合はYES、マップにアニメーションなしですぐに新しい領域を表示させる場合はNO。

討論

このメソッドを呼び出すと、領域プロパティの値が更新され、新しいマップ領域を反映するように他のプロパティが更新される可能性があります。


3

私はこれが古い質問であることを知っていますが、マップ上にすべての注釈を表示したい場合は、これを使用してください:

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

3

Mustafaの回答に対するSWIFTでの同等機能(動作確認済み:Xcode6.1、SDK 8.2)は次のとおりです。

func zoomToFitMapAnnotations() {
    if self.annotations.count == 0 {return}

    var topLeftCoordinate = CLLocationCoordinate2D(latitude: -90, longitude: 180)
    var bottomRightCoordinate = CLLocationCoordinate2D(latitude: 90, longitude: -180)

    for object in self.annotations {
        if let annotation = object as? MKAnnotation {
            topLeftCoordinate.longitude = fmin(topLeftCoordinate.longitude, annotation.coordinate.longitude)
            topLeftCoordinate.latitude = fmax(topLeftCoordinate.latitude, annotation.coordinate.latitude)
            bottomRightCoordinate.longitude = fmax(bottomRightCoordinate.longitude, annotation.coordinate.longitude)
            bottomRightCoordinate.latitude = fmin(bottomRightCoordinate.latitude, annotation.coordinate.latitude)
        }
    }

    let center = CLLocationCoordinate2D(latitude: topLeftCoordinate.latitude - (topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 0.5, longitude: topLeftCoordinate.longitude - (topLeftCoordinate.longitude - bottomRightCoordinate.longitude) * 0.5)

    print("\ncenter:\(center.latitude) \(center.longitude)")
    // Add a little extra space on the sides
    let span = MKCoordinateSpanMake(fabs(topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 1.01, fabs(bottomRightCoordinate.longitude - topLeftCoordinate.longitude) * 1.01)
    print("\nspan:\(span.latitudeDelta) \(span.longitudeDelta)")

    var region = MKCoordinateRegion(center: center, span: span)


    region = self.regionThatFits(region)

    self.setRegion(region, animated: true)

}

1
iOS_Developerさん、こんにちは。Swift変換に感謝します。topLeftCoordinate.latitudeとbottomRightCoordinate.longitudeの「fmin」の代わりに2つの「fmax」が欠落していると思うので、私にとっては機能しません。
Philipp Otto

2

考えられる解決策の1つは、現在の場所とすべての注釈の間の距離を測定し、MKCoordinateRegionMakeWithDistanceメソッドを使用して、最も遠い注釈よりわずかに大きい距離を持つ領域を作成することです。

もちろん、これはあなたが追加したアノテーションが多ければ多いほど遅くなります。


私は自分自身を検証するためだけにコメントセクションを通過していました。他の誰かが私と同じように考えていることを嬉しく思います:-) 2つの注釈(開始点と終了点)だけを追加しているので、遅延は感じられませんでした。
thandasoru 2013年

2
- (void)zoomToFitMapAnnotations {

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

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

//build array of annotation points
for (id<MKAnnotation> annotation in [self.mapview annotations])
    points[i++] = MKMapPointForCoordinate(annotation.coordinate);

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

[self.mapview setRegion:MKCoordinateRegionForMapRect([poly boundingMapRect]) animated:YES];
}

2

me2(現在はSwift)の優れた回答に基づいています

func coordinateRegionForCoordinates(coords: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
    var rect: MKMapRect = MKMapRectNull
    for coord in coords {
        let point: MKMapPoint = MKMapPointForCoordinate(coord)
        rect = MKMapRectUnion(rect, MKMapRectMake(point.x, point.y, 0, 0))
    }
    return MKCoordinateRegionForMapRect(rect)
}

1

mustufaのcoundコードスニペットに追加するために、1つの場所を処理するための少しのif句を追加しました。そのためにpkclSoftのzoomToAnnotation関数を使用しました。

if ([mapView.annotations count] == 1){
    MKCoordinateSpan span = {0.027, 0.027};
    region.span = span;
    CLLocationCoordinate2D singleCoordinate = [[mapView.annotations objectAtIndex:0] coordinate];
    region.center.latitude = singleCoordinate.latitude;
    region.center.longitude = singleCoordinate.longitude;
}
else
{
    // mustufa's code
}

1

このコードは私にとってはうまくいきます、それは現在の場所ですべてのピンを示します、これがあなたを助けることを願っています、

func setCenterForMap() {
    var mapRect: MKMapRect = MKMapRectNull
    for loc in mapView.annotations {
        let point: MKMapPoint = MKMapPointForCoordinate(loc.coordinate)
        print( "location is : \(loc.coordinate)");
        mapRect = MKMapRectUnion(mapRect, MKMapRectMake(point.x,point.y,0,0))
    }
    if (locationManager.location != nil) {
        let point: MKMapPoint = MKMapPointForCoordinate(locationManager.location!.coordinate)
        print( "Cur location is : \(locationManager.location!.coordinate)");
        mapRect = MKMapRectUnion(mapRect, MKMapRectMake(point.x,point.y,0,0))
    }

    mapView.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsetsMake(40.0, 40.0, 40.0, 40.0), animated: true)

}

0

私はこれが少なくとも関連していることを願っています、これは私がモノのためにまとめたものです(pkclSoftの答えに基づいて):

void ZoomMap (MKMapView map)
{
    var annotations = map.Annotations;

    if (annotations == null || annotations.Length == 0) 
        return;

    var points = annotations.OfType<MapAnnotation> ()
                            .Select (s => MKMapPoint.FromCoordinate (s.Coordinate))
                            .ToArray ();            

    map.SetVisibleMapRect(MKPolygon.FromPoints (points).BoundingMapRect, true); 
}

0
CLLocationCoordinate2D min = CLLocationCoordinate2DMake(99999.0, 99999.0);
CLLocationCoordinate2D max = CLLocationCoordinate2DMake(-99999.0, -99999.0);

// find max/min....

// zoom to cover area
// TODO: Maybe better using a MKPolygon which can calculate its own fitting region.
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((max.latitude + min.latitude) / 2.0, (max.longitude + min.longitude) / 2.0);
MKCoordinateSpan span = MKCoordinateSpanMake(max.latitude - min.latitude, max.longitude - min.longitude);
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);

[_mapView setRegion:[_mapView regionThatFits:region] animated:YES];

0

me2応答に基づいて、MKMapViewのカテゴリを作成して、マージンを追加し、ユーザーの場所の注釈をスキップしました。

@interface MKMapView (ZoomToFitAnnotations)
- (void)zoomToFitAnnotations:(BOOL)animated;
@end

@implementation MKMapView (ZoomToFitAnnotations)
- (void)zoomToFitAnnotations:(BOOL)animated {
    if (self.annotations.count == 0)
        return;

    MKMapRect rect = MKMapRectNull;
    for (id<MKAnnotation> annotation in self.annotations) {
        if ([annotation isKindOfClass:[MKUserLocation class]] == false) {
            MKMapPoint point = MKMapPointForCoordinate(annotation.coordinate);
            rect = MKMapRectUnion(rect, MKMapRectMake(point.x, point.y, 0, 0));
        }
    }

    MKCoordinateRegion region = MKCoordinateRegionForMapRect(rect);
    region.span.longitudeDelta *= 2; // Margin
    region.span.latitudeDelta *= 2; // Margin
    [self setRegion:region animated:animated];
}
@end

0

回答にコメントを付けることができないので、@ me2の回答に少し便利な点を加えたいと思います(ここで見つかった最もエレガントなアプローチだと思っていたため)。

私の個人的なプロジェクトでは、MKMapViewクラスにカテゴリを追加して、一般的な操作の「可視領域」機能をカプセル化しました。MKMapViewインスタンスに現在読み込まれているすべての注釈を表示できるように設定します。結果はこれでした:

.hファイル

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

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


@end

.mファイル

#import "MKMapView+Extensions.h"

@implementation MKMapView (Extensions)

/**
 *  Changes the currently visible portion of the map to a region that best fits all the currently loadded annotations on the map, and it optionally animates the change.
 *
 *  @param animated is the change should be perfomed with an animation.
 */
-(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated
{
    MKMapView * mapView = self;

    NSArray * annotations = mapView.annotations;

    [self ij_setVisibleRectToFitAnnotations:annotations animated:animated];

}


/**
 *  Changes the currently visible portion of the map to a region that best fits the provided annotations array, and it optionally animates the change.
    All elements from the array must conform to the <MKAnnotation> protocol in order to fetch the coordinates to compute the visible region of the map.
 *
 *  @param annotations an array of elements conforming to the <MKAnnotation> protocol, holding the locations for which the visible portion of the map will be set.
 *  @param animated    wether or not the change should be perfomed with an animation.
 */
-(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated
{
    MKMapView * mapView = self;

    MKMapRect r = MKMapRectNull;
    for (id<MKAnnotation> a in annotations) {
        ZAssert([a conformsToProtocol:@protocol(MKAnnotation)], @"ERROR: All elements of the array MUST conform to the MKAnnotation protocol. Element (%@) did not fulfill this requirement", a);
        MKMapPoint p = MKMapPointForCoordinate(a.coordinate);
        //MKMapRectUnion performs the union between 2 rects, returning a bigger rect containing both (or just one if the other is null). here we do it for rects without a size (points)
        r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
    }

    [mapView setVisibleMapRect:r animated:animated];

}

@end

ご覧のとおり、これまでに2つのメソッドを追加しました。1つはマップの可視領域を、MKMapViewインスタンスに現在読み込まれているすべての注釈に適合するメソッドに設定するメソッドと、それをオブジェクトの配列に設定するメソッドです。そのため、mapViewの可視領域を設定するには、コードは次のように単純です。

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

それが役に立てば幸いです=)


0

この拡張を検討してください:

extension MKCoordinateRegion {
    init(locations: [CLLocationCoordinate2D], marginMultiplier: Double = 1.1) {
        let mapRect = locations.reduce(MKMapRect(), {
            let point = MKMapPointForCoordinate($1)
            let rect = MKMapRect(origin: point, size: MKMapSize(width: 0.0, height: 0.0))
            return MKMapRectUnion($0, rect)
        })

        var coordinateRegion = MKCoordinateRegionForMapRect(mapRect)
        coordinateRegion.span.latitudeDelta *= marginMultiplier
        coordinateRegion.span.longitudeDelta *= marginMultiplier
        self = coordinateRegion
    }
}

0

Swift 5バージョン:

   func regionFor(coordinates coords: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
        var r = MKMapRect.null

        for i in 0 ..< coords.count {
            let p = MKMapPoint(coords[i])

            r = r.union(MKMapRect(x: p.x, y: p.y, width: 0, height: 0))
        }

        return MKCoordinateRegion(r)
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.