Respuestas:
Encontré una solución, que es muy simple y funciona. Use MKCoordinateRegionMakeWithDistance
para establecer la distancia en metros vertical y horizontalmente para obtener el zoom deseado. Y luego, por supuesto, cuando actualice su ubicación, obtendrá las coordenadas correctas, o puede especificarlas directamente CLLocationCoordinate2D
al inicio, si eso es lo que necesita hacer:
CLLocationCoordinate2D noLocation;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500);
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
[self.mapView setRegion:adjustedRegion animated:YES];
self.mapView.showsUserLocation = YES;
Rápido:
let location = ...
let region = MKCoordinateRegion( center: location.coordinate, latitudinalMeters: CLLocationDistance(exactly: 5000)!, longitudinalMeters: CLLocationDistance(exactly: 5000)!)
mapView.setRegion(mapView.regionThatFits(region), animated: true)
MKCoordinateRegionMakeWithDistance
todavía existe en Swift. ¡Esta solución funciona!
Basado en el hecho de que las líneas de longitud están espaciadas por igual en cualquier punto del mapa, existe una implementación muy simple para establecer centerCoordinate y 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));
No está integrado, pero he visto / usado este código. Esto le permite usar esto:
[mapView setCenterCoordinate:myCoord zoomLevel:13 animated:YES];
Nota: este no es mi código, no lo escribí, por lo que no puedo atribuirme el mérito
También puede hacer zoom utilizando MKCoordinateRegion y estableciendo su delta de latitud y longitud. A continuación se muestra una referencia rápida y aquí está la referencia de iOS. No hará nada elegante, pero debería permitirle establecer el zoom cuando dibuje el mapa.
MKCoordinateRegion region;
region.center.latitude = {desired lat};
region.center.longitude = {desired lng};
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
mapView.region = region;
Edición 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];
Una implementación simple de Swift, si usa puntos de venta.
@IBOutlet weak var mapView: MKMapView! {
didSet {
let noLocation = CLLocationCoordinate2D()
let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500)
self.mapView.setRegion(viewRegion, animated: false)
}
}
Basado en la respuesta de @ Carnal.
Implementación rápida
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
a tu map
, lo defines como un en MapViewWithZoom
lugar de un simple MKMapView
. Luego, puede configurar el nivel de zoom con map.zoomLevel = 1
omap.zoomLevel = 0.5
mapView.zoomLevel -= 2
Para Swift 3 es bastante rápido:
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)
}
Simplemente defina los metros de <CLLocationDistance>
latitud y longitud y mapView ajustará el nivel de zoom a sus valores.
Basado en la gran respuesta de @ AdilSoomro . Se me ocurrió esto:
@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
Espero que el siguiente fragmento de código te ayude.
- (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];
}
Puede elegir cualquier valor en lugar de 0,5 para reducir o aumentar el nivel de zoom. He utilizado estos métodos al hacer clic en dos botones.
Una respuesta de Swift 2.0 que utiliza NSUserDefaults para guardar y restaurar el zoom y la posición del mapa.
Función para guardar la posición del mapa y el zoom:
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")
}
Ejecute la función cada vez que se mueva el mapa:
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool)
{
saveMapRegion();
}
Función para guardar el zoom y la posición del mapa:
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)
}
}
Agregue esto para viewDidLoad:
restoreMapRegion()
Sé que esta es una respuesta tardía, pero solo quería abordar el problema de configurar el nivel de zoom yo mismo. La respuesta de goldmine es excelente, pero descubrí que no funciona lo suficientemente bien en mi aplicación.
En una inspección más cercana, goldmine afirma que "las líneas de longitud están separadas por igual en cualquier punto del mapa". Esto no es cierto, de hecho son las líneas de latitud que están espaciadas equitativamente desde -90 (polo sur) a +90 (polo norte). Las líneas de longitud están espaciadas en su punto más ancho en el ecuador, convergiendo a un punto en los polos.
La implementación que he adoptado es, por lo tanto, usar el cálculo de latitud de la siguiente manera:
@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
Espero que te ayude en esta última etapa.
Aquí, pongo mi respuesta y funciona para Swift 4.2 .
Basado en la respuesta de quentinadam
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
extensión basada en esta respuesta (+ precisión de nivel de zoom de punto flotante):
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)
}
}