MKMapView center and zoom in

后端 未结 9 1763
一向
一向 2021-02-19 23:16

I am using MKMapView on a project and would like to center the map on a coordinate and zoom in. Just like Google maps has:

GMSCameraPosition.camera(withLatitude:         


        
相关标签:
9条回答
  • 2021-02-19 23:32

    Swift 3.0

    In the MapKit Function didUpdateLocations:

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                guard let location = locations.last as CLLocation? else { return }
    
                let userCenter = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
                // Does not have to be userCenter, could replace latitude: and longitude: with any value you would like to center in on
    
                let region = MKCoordinateRegion(center: userCenter, span: MKCoordinateSpan(latitudeDelta: 180, longitudeDelta: 180))
    
                mkView.setRegion(region, animated: true)
    
        }
    

    Note: If you do not want to keep setting the center every time there is a location update, then do the following:

            let userCenter = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
            // Does not have to be userCenter, could replace latitude: and longitude: with any value you would like to center in on
    
            let region = MKCoordinateRegion(center: userCenter, span: MKCoordinateSpan(latitudeDelta: 180, longitudeDelta: 180))
    
            mkView.setRegion(region, animated: true)
    
    0 讨论(0)
  • 2021-02-19 23:33

    This works in swift 5, ios 13 and is easy to understand:

    Just add the following method to your class:

    func zoomAndCenter(on centerCoordinate: CLLocationCoordinate2D, zoom: Double) {
        var span: MKCoordinateSpan = mapView.region.span
        span.latitudeDelta *= zoom
        span.longitudeDelta *= zoom
        let region: MKCoordinateRegion = MKCoordinateRegion(center: centerCoordinate, span: span)
        mapView.setRegion(region, animated: true)
    }
    
    0 讨论(0)
  • 2021-02-19 23:36

    Base on apinho answer. This option follows Swift 5 syntax and allows to use it as an initializer of MKCoordinateRegion, so can be used in other objects beside MKMapView for example in MKMapSnapshotter.

    extension MKCoordinateRegion {
    
        init(center: CLLocationCoordinate2D, zoom: UInt, bounds: CGRect) {
            let zoom = min(zoom, 20)
            let span = MKCoordinateSpan(center: center, zoom: zoom, bounds: bounds)
            self.init(center: center, span: span)
        }
    }
    
    extension MKCoordinateSpan {
    
        static var mercatorOffset: Double {
            return 268435456.0
        }
    
        static var mercatorRadius: Double {
            return 85445659.44705395
        }
    
        private static func longitudeToPixelSpaceX(longitude: Double) -> Double {
            return round(mercatorOffset + mercatorRadius * longitude * Double.pi / 180.0)
        }
    
        private static func latitudeToPixelSpaceY(latitude: Double) -> Double {
            return round(mercatorOffset - mercatorRadius * log((1 + sin(latitude * Double.pi / 180.0)) / (1 - sin(latitude * Double.pi / 180.0))) / 2.0)
        }
    
        private static func pixelSpaceXToLongitude(pixelX: Double) -> Double {
            return ((round(pixelX) - mercatorOffset) / mercatorRadius) * 180.0 / Double.pi
        }
    
        private static func pixelSpaceYToLatitude(pixelY: Double) -> Double {
            return (Double.pi / 2.0 - 2.0 * atan(exp((round(pixelY) - mercatorOffset) / mercatorRadius))) * 180.0 / Double.pi
        }
    
        init(center: CLLocationCoordinate2D, zoom: UInt, bounds: CGRect) {
    
            let centerPixelX = MKCoordinateSpan.longitudeToPixelSpaceX(longitude: center.longitude)
            let centerPixelY = MKCoordinateSpan.latitudeToPixelSpaceY(latitude: center.latitude)
    
            let zoomExponent = Double(20 - zoom)
            let zoomScale = pow(2.0, zoomExponent)
    
            let mapSizeInPixels = bounds.size
            let scaledMapWidth =  Double(mapSizeInPixels.width) * zoomScale
            let scaledMapHeight = Double(mapSizeInPixels.height) * zoomScale
    
            let topLeftPixelX = centerPixelX - (scaledMapWidth / 2)
            let topLeftPixelY = centerPixelY - (scaledMapHeight / 2)
    
            // find delta between left and right longitudes
            let minLng = MKCoordinateSpan.pixelSpaceXToLongitude(pixelX: topLeftPixelX)
            let maxLng = MKCoordinateSpan.pixelSpaceXToLongitude(pixelX: topLeftPixelX + scaledMapWidth)
            let longitudeDelta = maxLng - minLng
    
            let minLat = MKCoordinateSpan.pixelSpaceYToLatitude(pixelY: topLeftPixelY)
            let maxLat = MKCoordinateSpan.pixelSpaceYToLatitude(pixelY: topLeftPixelY + scaledMapHeight)
            let latitudeDelta = -1 * (maxLat - minLat)
    
            self.init(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)
        }
    }
    
    0 讨论(0)
  • 2021-02-19 23:42

    Apinho answer in Swift 4.x

     extension MKMapView {
    
        var MERCATOR_OFFSET : Double {
            return 268435456.0
        }
    
        var MERCATOR_RADIUS : Double  {
            return 85445659.44705395
        }
    
        private func longitudeToPixelSpaceX(longitude: Double) -> Double {
            return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * Double.pi / 180.0)
        }
    
        private func latitudeToPixelSpaceY(latitude: Double) -> Double {
            return round(MERCATOR_OFFSET - MERCATOR_RADIUS * log((1 + sin(latitude * Double.pi / 180.0)) / (1 - sin(latitude * Double.pi / 180.0))) / 2.0)
        }
    
        private  func pixelSpaceXToLongitude(pixelX: Double) -> Double {
            return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / Double.pi;
        }
    
        private func pixelSpaceYToLatitude(pixelY: Double) -> Double {
            return (Double.pi / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / Double.pi;
        }
    
        private func coordinateSpan(withMapView mapView: MKMapView, centerCoordinate: CLLocationCoordinate2D, zoomLevel: UInt) ->MKCoordinateSpan {
            let centerPixelX = longitudeToPixelSpaceX(longitude: centerCoordinate.longitude)
            let centerPixelY = latitudeToPixelSpaceY(latitude: centerCoordinate.latitude)
    
            let zoomExponent = Double(20 - zoomLevel)
            let zoomScale = pow(2.0, zoomExponent)
    
            let mapSizeInPixels = mapView.bounds.size
            let scaledMapWidth =  Double(mapSizeInPixels.width) * zoomScale
            let scaledMapHeight = Double(mapSizeInPixels.height) * zoomScale
    
            let topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
            let topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
    
            // find delta between left and right longitudes
            let minLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX)
            let maxLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX + scaledMapWidth)
            let longitudeDelta = maxLng - minLng;
    
            let minLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY)
            let maxLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY + scaledMapHeight)
            let latitudeDelta = -1 * (maxLat - minLat);
    
            let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
            return span
        }
    
        func zoom(toCenterCoordinate centerCoordinate:CLLocationCoordinate2D, zoomLevel: UInt) {
            let zoomLevel = min(zoomLevel, 20)
            let span = self.coordinateSpan(withMapView: self, centerCoordinate: centerCoordinate, zoomLevel: zoomLevel)
            let region = MKCoordinateRegionMake(centerCoordinate, span)
            self.setRegion(region, animated: true)
    
        }
    }
    
    0 讨论(0)
  • 2021-02-19 23:45

    Code based on : http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/

        extension MKMapView {
        var MERCATOR_OFFSET : Double {
            return 268435456.0
        }
    
        var MERCATOR_RADIUS : Double  {
            return 85445659.44705395
        }
    
        private func longitudeToPixelSpaceX(longitude: Double) -> Double {
            return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0)
        }
    
        private func latitudeToPixelSpaceY(latitude: Double) -> Double {
            return round(MERCATOR_OFFSET - MERCATOR_RADIUS * log((1 + sin(latitude * M_PI / 180.0)) / (1 - sin(latitude * M_PI / 180.0))) / 2.0)
        }
    
        private  func pixelSpaceXToLongitude(pixelX: Double) -> Double {
            return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
        }
    
        private func pixelSpaceYToLatitude(pixelY: Double) -> Double {
            return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
        }
    
        private func coordinateSpan(withMapView mapView: MKMapView, centerCoordinate: CLLocationCoordinate2D, zoomLevel: UInt) ->MKCoordinateSpan {
            let centerPixelX = longitudeToPixelSpaceX(centerCoordinate.longitude)
            let centerPixelY = latitudeToPixelSpaceY(centerCoordinate.latitude)
    
            let zoomExponent = Double(20 - zoomLevel)
            let zoomScale = pow(2.0, zoomExponent)
    
            let mapSizeInPixels = mapView.bounds.size
            let scaledMapWidth =  Double(mapSizeInPixels.width) * zoomScale
            let scaledMapHeight = Double(mapSizeInPixels.height) * zoomScale
    
            let topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
            let topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
    
            //    // find delta between left and right longitudes
            let minLng = pixelSpaceXToLongitude(topLeftPixelX)
            let maxLng = pixelSpaceXToLongitude(topLeftPixelX + scaledMapWidth)
            let longitudeDelta = maxLng - minLng;
    
            let minLat = pixelSpaceYToLatitude(topLeftPixelY)
            let maxLat = pixelSpaceYToLatitude(topLeftPixelY + scaledMapHeight)
            let latitudeDelta = -1 * (maxLat - minLat);
    
            let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
            return span
        }
    
        func zoom(toCenterCoordinate centerCoordinate:CLLocationCoordinate2D ,zoomLevel: UInt) {
            let zoomLevel = min(zoomLevel, 20)
            let span = self.coordinateSpan(withMapView: self, centerCoordinate: centerCoordinate, zoomLevel: zoomLevel)
            let region = MKCoordinateRegionMake(centerCoordinate, span)
            self.setRegion(region, animated: true)
    
        }
    }
    
    0 讨论(0)
  • 2021-02-19 23:45

    This is working code tested on swift 4.2

     override func viewDidLoad() {
        super.viewDidLoad()
        let initialLocation = CLLocation(latitude: 28.5761897, longitude: 77.172080)
        self.centerMapOnLocation(location: initialLocation)
    }
    
    
     func centerMapOnLocation(location: CLLocation) {
        let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
        DispatchQueue.main.async {
            self.mapView.setRegion(region, animated: true)
            let annotation = MKPointAnnotation()
            annotation.coordinate = location.coordinate
            self.mapView.addAnnotation(annotation)
        }
    }
    

    This will load with animation. Hope will help you.

    0 讨论(0)
提交回复
热议问题