Ответы:
Я нашел себе решение, которое очень простое и помогает. Используйте 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;
Swift:
let location = ...
let region = MKCoordinateRegion( center: location.coordinate, latitudinalMeters: CLLocationDistance(exactly: 5000)!, longitudinalMeters: CLLocationDistance(exactly: 5000)!)
mapView.setRegion(mapView.regionThatFits(region), animated: true)
MKCoordinateRegionMakeWithDistance
что в Swift все еще присутствует. Это решение работает!
Основываясь на том факте, что линии долготы разнесены одинаково в любой точке карты, существует очень простая реализация для установки 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]; }
double z = log2(360 * ((self.mapView.frame.size.width/256) / self.mapView.region.span.longitudeDelta));
Он не встроен, но я видел / использовал этот код. Это позволяет вам использовать это:
[mapView setCenterCoordinate:myCoord zoomLevel:13 animated:YES];
Примечание: это не мой код, я его не писал, поэтому не могу брать на себя ответственность
Вы также можете масштабировать, используя 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];
Простая реализация Swift, если вы используете розетки.
@IBOutlet weak var mapView: MKMapView! {
didSet {
let noLocation = CLLocationCoordinate2D()
let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500)
self.mapView.setRegion(viewRegion, animated: false)
}
}
На основе ответа @Carnal.
Быстрая реализация
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)
}
}
IBOutlet
для своего map
, вы определяете его как MapViewWithZoom
вместо простого MKMapView
. Затем вы можете просто установить уровень масштабирования с помощью map.zoomLevel = 1
илиmap.zoomLevel = 0.5
mapView.zoomLevel -= 2
Для Swift 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>
широту и долготу в метрах, и mapView подберет уровень масштабирования для ваших значений.
На основе отличного ответа @ 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
Надеюсь, следующий фрагмент кода вам поможет.
- (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, чтобы уменьшить или увеличить уровень масштабирования. Я использовал эти методы при нажатии двух кнопок.
Ответ Swift 2.0 с использованием NSUserDefaults для сохранения и восстановления масштаба и положения карты.
Функция сохранения положения карты и масштабирования:
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()
Я знаю, что это запоздалый ответ, но я просто хотел сам решить проблему установки уровня масштабирования. Ответ goldmine отличный, но я обнаружил, что он недостаточно хорошо работает в моем приложении.
При ближайшем рассмотрении в 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
Надеюсь, это поможет на этом позднем этапе.
Здесь я помещаю свой ответ и его работу для быстрой версии 4.2 .
На основе ответа Квентинадама
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))
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)
}
}