MKMapViewのズームレベルの設定


118

正しく表示されるマップがあります。ロードするときにズームレベルを設定するだけです。これを行う方法はありますか?

ありがとう

回答:


198

私は自分で解決策を見つけました。これは非常に簡単で、トリックを実行します。MKCoordinateRegionMakeWithDistance距離を垂直方向と水平方向にメートル単位で設定して、目的のズームを取得するために使用します。そして、もちろん、あなたがあなたの場所を更新するとき、あなたは正しい座標を得るでしょう、あるいはそれがあなたがするCLLocationCoordinate2D必要があるものならば、あなたはスタートアップでそれを直接指定することができます:

CLLocationCoordinate2D noLocation;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500);
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];          
[self.mapView setRegion:adjustedRegion animated:YES];
self.mapView.showsUserLocation = YES;

迅速:

let location = ...
let region = MKCoordinateRegion( center: location.coordinate, latitudinalMeters: CLLocationDistance(exactly: 5000)!, longitudinalMeters: CLLocationDistance(exactly: 5000)!)
mapView.setRegion(mapView.regionThatFits(region), animated: true)

3
これが選択された答えです。他の提案された解決策をたくさん試しましたが、どれも適切に機能しませんでした。このコードはシンプルで効果的です。
Levi Roberts

1
素敵な答え。ただし、ズームは画面サイズによって異なりますか?
Vinzius

1
興味深いことに、MKCoordinateRegionMakeWithDistanceまだSwiftにあります。このソリューションは機能します!
LinusGeffarth

47

経度線がマップのどのポイントでも等間隔に配置されているという事実に基づいて、centerCoordinateおよびzoomLevelを設定するための非常に単純な実装があります。

@interface MKMapView (ZoomLevel)

@property (assign, nonatomic) NSUInteger zoomLevel;

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel
                   animated:(BOOL)animated;

@end


@implementation MKMapView (ZoomLevel)

- (void)setZoomLevel:(NSUInteger)zoomLevel {
    [self setCenterCoordinate:self.centerCoordinate zoomLevel:zoomLevel animated:NO];
}

- (NSUInteger)zoomLevel {
    return log2(360 * ((self.frame.size.width/256) / self.region.span.longitudeDelta)) + 1;
}

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated {
    MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256);
    [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated];
}

@end

細かい修正:- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated { MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256); [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated]; }
Monobono 2013

ありがとう!はい、そうです。実際には、MKMapViewへの追加ではなく関数であるプロジェクトからコードを取り出しました。修正を反映するようにコードを編集しました。
クエンティナダム2013

1
現在のズームレベルを計算するために、その式の逆は何ですか?
Nick

1
私はこれだと思います:double z = log2(360 * ((self.mapView.frame.size.width/256) / self.mapView.region.span.longitudeDelta));
Nick

1
@devios、ズームレベル1では、全世界(360°)が幅256pxの1タイルに収まります。ズームレベル2では、全世界(360°)が256px(512px)の2タイルに収まります。ズームレベル3では、全世界(360°)が256ピクセル(1024ピクセル)の4タイルに収まるなど
quentinadam

31

組み込まれていませんが、このコードを確認/使用しました。これにより、これを使用できます。

[mapView setCenterCoordinate:myCoord zoomLevel:13 animated:YES];

注:これは私のコードではありません。私はコードを記述しなかったため、それを信用できません。


1
うわー、その多くのコード、あなたはそれが組み込まれるべきだと思います。ありがとう。どのようにそれが行われたかを見ていきます。
システム

1
.mおよび.hファイルを取得してプロジェクトに追加し、それをマップビューコントローラーで参照して、まるでMKMapViewのメソッドであるかのように使用できます。
PostMan

2
うまくいきませんでした。以前と同じズームレベルが表示されるだけです。私は何か間違ったことをしているに違いありません。
システム

17

MKCoordinateRegionを使用し、そのスパンの緯度と経度のデルタを設定してズームすることもできます。以下はクイックリファレンスで、こちらがiOSリファレンスです。特別なことは何もしませんが、マップを描画するときにズームを設定できるようにする必要があります。


MKCoordinateRegion region;
region.center.latitude = {desired lat};
region.center.longitude = {desired lng};
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
mapView.region = region;

編集1:

MKCoordinateRegion region;
region.center.latitude = {desired lat};
region.center.longitude = {desired lng};
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:TRUE];

1
これは私にとって何の違いもありませんでした。いくつかの値を変更すると、マップが読み込まれません。
システム

これは、マップのロード時に設定していますか、それともロードの実行後に操作しようとしていますか?デルタとして1以下の数を使用していますか?要件を理解しようとしています。
DerekH 2010年

実行前に設定しました。私は1の上下の値をテストしました
システムの

1
良い答えですが、緯度、経度のデルタを0.1に変更してみてください-より拡大されます。
Daniel Krzyczkowski

12

アウトレットを使用する場合の単純なSwift実装。

@IBOutlet weak var mapView: MKMapView! {
    didSet {
        let noLocation = CLLocationCoordinate2D()
        let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500)
        self.mapView.setRegion(viewRegion, animated: false)
    }
}

@Carnalの答えに基づいています。


12

Swiftの実装

import Foundation
import MapKit

class MapViewWithZoom: MKMapView {

    var zoomLevel: Int {
        get {
            return Int(log2(360 * (Double(self.frame.size.width/256) / self.region.span.longitudeDelta)) + 1);
        }

        set (newZoomLevel){
            setCenterCoordinate(coordinate:self.centerCoordinate, zoomLevel: newZoomLevel, animated: false)
        }
    }

    private func setCenterCoordinate(coordinate: CLLocationCoordinate2D, zoomLevel: Int, animated: Bool) {
        let span = MKCoordinateSpan(latitudeDelta: 0, longitudeDelta: 360 / pow(2, Double(zoomLevel)) * Double(self.frame.size.width) / 256)
        setRegion(MKCoordinateRegion(center: coordinate, span: span), animated: animated)
    }
}

1
私は確かに100%ではないんだけど、私はあなたを作成するときに推測IBOutletあなたにmap、あなたのようにそれを定義MapViewWithZoom代わりにシンプルなのMKMapView。次に、map.zoomLevel = 1またはmap.zoomLevel = 0.5
Zonker.in.Geneva '10

1
これに関するいくつかのコメントがより役立つでしょうSwift 3で機能しています
nyxee

素晴らしい解決策!しかし、私はそれを拡張機能としてより好きにして、奇妙なことが1つあります。実際にズームアウトするには、2のように2だけ減らす必要がありますmapView.zoomLevel -= 2
Alexander

7

スウィフト3それはかなり早送りです。

private func setMapRegion(for location: CLLocationCoordinate2D, animated: Bool)
{
    let viewRegion = MKCoordinateRegionMakeWithDistance(location, <#T##latitudinalMeters: CLLocationDistance##CLLocationDistance#>, <#T##longitudinalMeters: CLLocationDistance##CLLocationDistance#>)
    MapView.setRegion(viewRegion, animated: animated)
}

lat-、long-Meters <CLLocationDistance>を定義するだけで、mapViewはズームレベルを値に合わせます。


「mapViewがズームレベルをあなたの値に合わせる」とはどういう意味ですか?OPがズームレベルを自分で設定する必要があると思いますか?
riper

6

@AdilSoomroの素晴らしい回答に基づいています。私はこれを思いつきました:

@interface MKMapView (ZoomLevel)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel
                   animated:(BOOL)animated;

-(double) getZoomLevel;
@end



@implementation MKMapView (ZoomLevel)

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated {
    MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256);
    [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated];
}


-(double) getZoomLevel {
    return log2(360 * ((self.frame.size.width/256) / self.region.span.longitudeDelta));
}

@end

3

次のコードの断片がお役に立てば幸いです。

- (void)handleZoomOutAction:(id)sender {
    MKCoordinateRegion newRegion=MKCoordinateRegionMake(mapView.region.center,MKCoordinateSpanMake(mapView.region.s       pan.latitudeDelta/0.5, mapView.region.span.longitudeDelta/0.5));
    [mapView setRegion:newRegion];
}


- (void)handleZoomInAction:(id)sender {
    MKCoordinateRegion newRegion=MKCoordinateRegionMake(mapView.region.center,MKCoordinateSpanMake(mapView.region.span.latitudeDelta*0.5, mapView.region.span.longitudeDelta*0.5));
    [mapView setRegion:newRegion];
}

0.5の代わりに任意の値を選択して、ズームレベルを増減できます。私は2つのボタンをクリックするときにこれらの方法を使用しました。


2

NSUserDefaultsを利用してマップのズームと位置を保存および復元するSwift 2.0の回答。

地図の位置を保存してズームする機能:

func saveMapRegion() {
    let mapRegion = [
        "latitude" : mapView.region.center.latitude,
        "longitude" : mapView.region.center.longitude,
        "latitudeDelta" : mapView.region.span.latitudeDelta,
        "longitudeDelta" : mapView.region.span.longitudeDelta
    ]
    NSUserDefaults.standardUserDefaults().setObject(mapRegion, forKey: "mapRegion")
}

マップが移動するたびに関数を実行します。

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) 
{
        saveMapRegion();
}

地図のズームと位置を保存する関数:

func restoreMapRegion() 
{
    if let mapRegion = NSUserDefaults.standardUserDefaults().objectForKey("mapRegion") 
    {

        let longitude = mapRegion["longitude"] as! CLLocationDegrees
        let latitude = mapRegion["latitude"] as! CLLocationDegrees
        let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)

        let longitudeDelta = mapRegion["latitudeDelta"] as! CLLocationDegrees
        let latitudeDelta = mapRegion["longitudeDelta"] as! CLLocationDegrees
        let span = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)

        let savedRegion = MKCoordinateRegion(center: center, span: span)

        self.mapView.setRegion(savedRegion, animated: false)
    }
}

これをviewDidLoadに追加します。

restoreMapRegion()

1

これは返信が遅いことはわかっていますが、ズームレベルを自分で設定する問題に対処したいと思っています。goldmineの答えは素晴らしいですが、アプリケーションで十分に機能しないことがわかりました。

金鉱の詳細な調査では、「経度線は地図のどの点でも等間隔に配置されている」と述べています。これは真実ではなく、実際には-90(南極)から+90(北極)まで等間隔に配置された緯度線です。経度線は赤道で最も幅が広く、極点で収束します。

したがって、私が採用した実装では、緯度の計算を次のように使用しています。

@implementation MKMapView (ZoomLevel)

- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate
    zoomLevel:(NSUInteger)zoom animated:(BOOL)animated
{
    MKCoordinateSpan span = MKCoordinateSpanMake(180 / pow(2, zoom) * 
        self.frame.size.height / 256, 0);
    [self setRegion:MKCoordinateRegionMake(coordinate, span) animated:animated];
}

@end

この後半の段階で役立つことを願っています。


上記は無視してください。Goldmineは正しいです。もちろん、マップにはメルカトル図法が使用されているため、経度線は等間隔に配置されます。ソリューションに関する私の問題は、新しいiOS 7 MKTileOverlayクラスのサブクラス化に関するアプリケーションの別のマイナーなバグが原因でした。
gektron 2013

コメントに含めた情報を反映するように投稿を更新することを検討してください。
デレク・リー

1

迅速:

Map.setRegion(MKCoordinateRegion(center: locValue, latitudinalMeters: 200, longitudinalMeters: 200), animated: true)

locValueは座標です。


1

ここで、私は私の答えとその作業を迅速な4.2に置きました。

MKMapViewの中心とズームイン


私はこちらをクリックして下にスクロールして、そこにあなたのリンクをクリックすると、私は再びここに自分自身を見つけるだろうし、私はこちらをクリックして、今、私は😏無限ループでこだわっている
Matthijs

@Matthijsリンクを修正しました。回答を確認して投票してください。
アシュ

0

クエンティナダムの答えに基づく

Swift 5.1

// size refers to the width/height of your tile images, by default is 256.0
// Seems to get better results using round()
// frame.width is the width of the MKMapView

let zoom = round(log2(360 * Double(frame.width) / size / region.span.longitudeDelta))

ありがとう、地図が北を向いているように見えます。しかし、マップを回転させている場合はどうでしょうか?ピンチ角度が0と異なる場合はどうなりますか?
pierre23

0

MKMapViewこの回答に基づく拡張(+浮動小数点ズームレベルの精度):

import Foundation
import MapKit

extension MKMapView {
    var zoomLevel: Double {
        get {
            return log2(360 * (Double(self.frame.size.width / 256) / self.region.span.longitudeDelta)) + 1
        }

        set (newZoomLevel){
            setCenterCoordinate(coordinate:self.centerCoordinate, zoomLevel: newZoomLevel, animated: false)
        }
    }

    private func setCenterCoordinate(coordinate: CLLocationCoordinate2D, zoomLevel: Double, animated: Bool) {
        let span = MKCoordinateSpan(latitudeDelta: 0, longitudeDelta: 360 / pow(2, zoomLevel) * Double(self.frame.size.width) / 256)
        setRegion(MKCoordinateRegion(center: coordinate, span: span), animated: animated)
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.