MKMapView의 확대 / 축소 수준 설정


118

올바르게 표시되는지도가 있는데로드 할 때 확대 / 축소 수준을 설정하는 것뿐입니다. 이를 수행하는 방법이 있습니까?

감사

답변:


200

나는 매우 간단하고 트릭을 수행하는 해결책을 찾았습니다. 사용하여 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에 추가하는 것이 아니라 함수 인 프로젝트에서 코드를 가져 왔습니다. 귀하의 수정 사항을 반영하기 위해 방금 코드를 편집했습니다.
quentinadam 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 °)는 256px (1024px) 등의 타일 4 개에 맞습니다.
quentinadam

31

내장되어 있지 않지만 코드를 보거나 사용 했습니다 . 이를 통해 다음을 사용할 수 있습니다.

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

참고 : 이것은 내 코드가 아니므로 작성하지 않았으므로 크레딧을받을 수 없습니다.


1
와우, 그것의 많은 코드, u는 그것이 내장되어야한다고 생각할 것입니다. 감사합니다. 그것의 끝을 볼 것입니다.
시스템

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 위와 아래의 값을 테스트했습니다.
system

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

신속한 구현

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

1
이에 대한 몇 가지 의견 그것은 3 스위프트에서 일하고 더 도움이 될 것입니다
nyxee

훌륭한 솔루션! 하지만 저는 확장 프로그램으로 더 좋아합니다. 한 가지 이상한 점이 있습니다. 실제로 축소하려면 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)
}

<CLLocationDistance>lat- , long-Meters를 정의하기 만하면 mapView가 확대 / 축소 수준을 값에 맞 춥니 다.


"mapView가 귀하의 값에 확대 / 축소 수준을 맞출 것"이란 무엇을 의미합니까? OP가 확대 / 축소 수준을 직접 설정하고 싶거나 제안한 입력이 주어지면 어떻게할까요?

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

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

여기에 내 대답과 그 작업을 swift 4.2 .

MKMapView 센터 및 확대


여기를 클릭하고 아래로 스크롤하여 링크를 클릭하면 다시 여기에서 자신을 찾은 다음 여기를 클릭하면 무한 루프에 갇혀 있습니다 😏
Matthijs

@Matthijs 링크를 수정했습니다. 답을 확인하고 투표하십시오.
Ashu

0

quentinadam의 답변에 따라

스위프트 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.