MKMapView için yakınlaştırma düzeyini ayarlama


118

Doğru gösteren bir haritam var, şimdi yapmak istediğim tek şey yüklendiğinde yakınlaştırma seviyesini ayarlamak. Bunu yapmanın bir yolu var mı?

Teşekkürler

Yanıtlar:


200

Kendime bir çözüm buldum, bu çok basit ve hile yapıyor. MKCoordinateRegionMakeWithDistanceİstenilen yakınlaştırmayı elde etmek için mesafeyi dikey ve yatay olarak metre cinsinden ayarlamak için kullanın . Ve sonra tabii ki konumunuzu güncellediğinizde doğru koordinatları alacaksınız ya da CLLocationCoordinate2Dyapmanız gereken şey buysa, bunu başlangıçta doğrudan belirtebilirsiniz :

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

Swift:

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

3
Bu seçilen cevap olmalıdır. Önerilen diğer birçok çözümü denedim ama hiçbiri düzgün çalışmadı. Bu kod basit ve etkilidir.
Levi Roberts

1
Güzel cevap. Ancak yakınlaştırma ekran boyutuna bağlı olarak farklı olacaktır, değil mi?
Vinzius

1
İlginç bir şekilde, MKCoordinateRegionMakeWithDistancehala Swift'de. Bu çözüm işe yarıyor!
LinusGeffarth

47

Boylam çizgilerinin haritanın herhangi bir noktasında eşit aralıklarla yerleştirildiği gerçeğine dayanarak, merkez Koordinat ve yakınlaştırma Seviyesini ayarlamak için çok basit bir uygulama vardır:

@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

Küçük düzeltmeler:- (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

Teşekkürler! Evet haklısınız, aslında kodu MKMapView'e ek olarak değil, bir işlev olduğu projemden çıkardım. Düzeltmenizi yansıtmak için kodu düzenledim.
quentinadam

1
Mevcut yakınlaştırma düzeyini hesaplamak için bu formülün tersi nedir?
Nick

1
Sanırım şu:double z = log2(360 * ((self.mapView.frame.size.width/256) / self.mapView.region.span.longitudeDelta));
Nick

1
@devios, 1. yakınlaştırma düzeyinde, tüm dünya (360 °), 256 piksel genişliğinde 1 karoya sığar. Yakınlaştırma düzeyi 2'de, tüm dünya (360 °) 256 piksellik (512 piksel) 2 parçaya sığar. Yakınlaştırma düzeyinde 3, tüm dünya (360 °) 256 piksellik (1024 piksel) vb. 4 parçaya sığar
quentinadam

31

Yerleşik değil, ancak bu kodu gördüm / kullandım . Bu, şunu kullanmanıza izin verir:

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

Not: Bu benim kodum değil, ben yazmadım, bu yüzden kredi alamam


1
vay, çok fazla kod var, yerleşik olması gerektiğini düşünürdüm. teşekkürler. nasıl yapıldığına bir göz atacak.
Sistem

1
.M ve .h dosyalarını edinebilir, projenize ekleyebilir, ardından harita görünümü denetleyicinizde referans verebilir ve MKMapView'da bir yöntemmiş gibi kullanabilirsiniz, kategorilerin eğlenceleri!
PostMan

2
Benim için işe yaramadı, sadece öncekiyle aynı yakınlaştırma seviyesini gösteriyor. Yanlış bir şey yapıyor olmalıyım.
sistem

17

MKCoordinateRegion'u kullanarak ve yayılma enlem ve boylam deltasını ayarlayarak da yakınlaştırabilirsiniz. Aşağıda hızlı bir referans ve işte iOS referansı. Süslü bir şey yapmaz, ancak haritayı çizerken yakınlaştırmayı ayarlamanıza izin vermelidir.


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

Düzenleme 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
Bu benim için bir fark yaratmadı, bazı değerleri değiştirdiğimde haritayı yüklemiyor.
sistem

Bunu harita yüklendiğinde mi ayarlıyorsunuz yoksa yükleme gerçekleştikten sonra değiştirmeye mi çalışıyorsunuz? Deltalarınız olarak 1 veya daha küçük bir sayı mı kullanıyorsunuz? Sadece gereksinimleri anlamaya çalışıyorum.
DerekH

Çalışma zamanından önce ayarladım. 1'in üzerindeki ve altındaki değerleri test ettim.
sistem

1
İyi cevap, ancak enlemi, boylam deltasını 0,1 olarak değiştirmeyi deneyin - daha fazla yakınlaştırıldı.
Daniel Krzyczkowski

12

Çıkışları kullanıyorsanız basit bir Swift uygulaması.

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

@ Carnal'ın cevabına göre.


12

Hızlı uygulama

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
Ben emin% 100 değilim, ama ben size oluştururken tahmin IBOutletadresinden Müşteri map, bir olarak tanımlamak MapViewWithZoomyerine basit bir MKMapView. Ardından, yakınlaştırma düzeyini map.zoomLevel = 1veya ile ayarlayabilirsinizmap.zoomLevel = 0.5
Zonker.in.Geneva

1
bununla ilgili bazı yorumlar daha yararlı olabilir. Swift 3'te çalışıyor
nyxee

Harika çözüm! Ama bunu bir Uzantı olarak daha çok seviyorum ve tuhaf bir şey var: Aslında uzaklaştırmak için 2 gibi azaltmanız gerekiyormapView.zoomLevel -= 2
Alexander

7

İçin Swift 3 oldukça hızlı ileri bulunuyor:

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

<CLLocationDistance>Enlem , uzun Metre'yi tanımlamanız yeterlidir; mapView yakınlaştırma düzeyini değerlerinize sığdırır.


"MapView yakınlaştırma düzeyini değerlerinize sığdıracak" derken neyi kastediyorsunuz? OP'nin yakınlaştırma düzeyini kendisinin ayarlamak istediğini varsayıyorum veya önerdiğiniz girdiye göre bunu nasıl yapardınız?
riper

6

@ AdilSoomro'nun harika cevabına dayanmaktadır . Ben şunu buldum:

@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

Umarım aşağıdaki kod parçası size yardımcı olur.

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

Yakınlaştırma düzeyini azaltmak veya artırmak için 0,5 yerine herhangi bir değer seçebilirsiniz. Bu yöntemleri iki düğmeyi tıklatarak kullandım.


2

Haritanın yakınlaştırma ve konumunu kaydetmek ve geri yüklemek için NSUserDefaults kullanan bir Swift 2.0 yanıtı.

Harita konumunu kaydetme ve yakınlaştırma işlevi:

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

Harita her hareket ettirildiğinde işlevi çalıştırın:

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

Harita yakınlaştırmasını ve konumunu kaydetme işlevi:

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

Bunu viewDidLoad'a ekle:

restoreMapRegion()

1

Bunun geç bir cevap olduğunu biliyorum, ancak yakınlaştırma düzeyini kendim belirleme sorununu çözmek istedim. Goldmine'nin cevabı harika ama başvurumda yeterince iyi çalışmadığını gördüm.

Daha yakından incelendiğinde altın madeni, "boylam çizgilerinin haritanın herhangi bir noktasında eşit aralıklarla yerleştirildiğini" belirtir. Bu doğru değil, aslında -90 (güney kutbu) ile +90 (kuzey kutbu) arasında eşit aralıklı enlem çizgileridir. Boylam çizgileri ekvatorda en geniş aralıklarıyla kutuplarda bir noktaya yakınsar.

Bu nedenle benimsediğim uygulama, enlem hesaplamasını aşağıdaki gibi kullanmaktır:

@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

Umarım bu geç aşamada yardımcı olur.


Tamam yukarıdakileri görmezden gelin. Goldmine doğru, boylam çizgileri eşit aralıklı OLDU çünkü haritalar için Mercator projeksiyonu kullanılıyor. Çözümle ilgili sorunlarım, yeni iOS 7 MKTileOverlay sınıfını alt sınıflara ayırmakla ilgili uygulamamdaki başka bir küçük hatadan kaynaklanıyor.
gektron

Yorumunuza eklediğiniz bilgileri yansıtmak için yayınınızı güncellemeyi düşünebilirsiniz.
Derek Lee

1

Swift:

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

locValue sizin koordinatınızdır.


1

Buraya cevabımı koyuyorum ve hızlı 4.2 için çalışıyor .

Merkezi görüntüleyin ve yakınlaştırın


Buraya tıklayıp aşağı kaydırırsam ve oradaki bağlantınıza tıklarsam, kendimi burada tekrar bulacağım ve sonra buraya tıklarım ve şimdi sonsuz bir döngü içinde sıkışıp kaldım 😏
Matthijs

@Matthijs Bağlantıyı düzelttim. Lütfen yanıtı kontrol edin ve oylayın.
Ashu

0

Quentinadam'ın cevabına göre

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

Teşekkürler, harita kuzeye bakarken güzel görünüyor. Peki ya haritayı döndürüyorsanız? Ya sıkıştırma açısı 0'dan farklıysa?
pierre23

0

MKMapViewbu yanıta dayalı uzantı (+ kayan noktalı yakınlaştırma düzeyi doğruluğu):

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)
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.