美文网首页
地图和定位(四)

地图和定位(四)

作者: weyan | 来源:发表于2020-03-07 16:16 被阅读0次

    一、地图的基本使用(MapKit)

    普通地图 卫星地图 混合模式(相比卫星地图多一些标识和路线) 3D立体卫星 3D立体混合

    代码:

    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var mapView: MKMapView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //设置地图的类型
            mapView.mapType = .standard
            
            //设置地图的控制项
            mapView.isScrollEnabled = true
            mapView.isRotateEnabled = true
            mapView.isZoomEnabled = true
            
            //设置地图的显示项
            //建筑物
            mapView.showsBuildings = true
            //指南针 
            mapView.showsCompass = true
            //POI兴趣点 学校,医院...
            mapView.showsPointsOfInterest = true
            //比例尺
            mapView.showsScale = true
            //交通状况
            mapView.showsTraffic = true
            //用户所在的位置
            mapView.showsUserLocation = true;
        }
    }
    
    效果图1

    二、地图显示用户位置

    显示用户的位置信息 地图跟随用户位置移动
    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var mapView: MKMapView!
        
        lazy var locationM: CLLocationManager? = {
            let locationM = CLLocationManager()
            return locationM
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //设置地图的类型
            mapView.mapType = .standard
            
            //设置地图的控制项
            mapView.isScrollEnabled = true
            mapView.isRotateEnabled = true
            mapView.isZoomEnabled = true
            
            //设置地图的显示项
            //建筑物
            mapView.showsBuildings = true
            
            if #available(iOS 9.0, *) {
                //指南针 学校,医院...
                mapView.showsCompass = true
                //比例尺
                mapView.showsScale = true
                //交通状况
                mapView.showsTraffic = true
            }
            //POI兴趣点
            mapView.showsPointsOfInterest = true
            
            //用户所在的位置
            //1.请求定位授权
            if #available(iOS 8.0, *) {
                locationM?.requestAlwaysAuthorization()
            }
            //效果:就是一个蓝点,标识用户的位置信息
            //弊端:不会自动调整地图比例,另外当用户移动时地图不会跟着走。
    //        mapView.showsUserLocation = true;
            
            //设置用户追踪模式
            //会自动放大地图到合适的比例
            //当用户位置移动时,会自动移动地图的位置信息(但不灵光)
            mapView.userTrackingMode = .followWithHeading;
            
        }
    }
    

    三、模拟追踪显示用户位置

    1、显示用户位置的蓝点

    代码:

    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var mapView: MKMapView!
        
        //懒加载
        lazy var locationManager: CLLocationManager = {
            let locationManager = CLLocationManager()
            return locationManager
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            mapView.delegate = self
            //0. 请求用户授权
            if #available(iOS 8.0, *) {
                locationManager.requestAlwaysAuthorization()
            }
            //1.显示用户位置的蓝点
            mapView.showsUserLocation = true
        }
    }
    
    
    extension ViewController: MKMapViewDelegate{
        /**获取用户位置信息
       * mapView 地图
       * userLocation 大头针数据模型
       */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //MKUserLocation: "大头针数据模型",其实叫什么都可以,只不过这个类遵循了大头针数据模型必须遵循的一个协议MKAnnotation
            //验证当前的userLocation,对应的大头针视图就是我们看到的蓝点
            userLocation.title = "大哥"
            userLocation.subtitle = "打你"
        }
    }
    

    2、调整地图中心

    效果:只是调整地图的显示中心,但不会自动放大地图
    extension ViewController: MKMapViewDelegate{
        /**获取用户位置信息
       * mapView 地图
       * userLocation 大头针数据模型
       */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //MKUserLocation: "大头针数据模型",其实叫什么都可以,只不过这个类遵循了大头针数据模型必须遵循的一个协议MKAnnotation
            //验证当前的userLocation,对应的大头针视图就是我们看到的蓝点
            //coordinate: CLLocationCoordinate2D确定当前大头针插在哪个位置
            userLocation.title = "大哥"
            userLocation.subtitle = "打你"
            print("location:\(userLocation.coordinate)")
            
            //2.调整地图中心(显示用户的位置信息后,通过控制地图的中心坐标来不断跟随用户位置)
            //效果:只是调整地图的显示中心,但不会自动放大地图
            mapView.setCenter(userLocation.coordinate, animated: true)
        }
    }
    

    3、设置地图显示区域

    3步都完成后的效果图
    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var mapView: MKMapView!
        
        //懒加载
        lazy var locationManager: CLLocationManager = {
            let locationManager = CLLocationManager()
            return locationManager
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            mapView.delegate = self
            //0. 请求用户授权
            if #available(iOS 8.0, *) {
                locationManager.requestAlwaysAuthorization()
            }
            //1.显示用户位置的蓝点
            mapView.showsUserLocation = true
        }
    }
    
    
    extension ViewController: MKMapViewDelegate{
        /**获取用户位置信息
       * mapView 地图
       * userLocation 大头针数据模型
       */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //MKUserLocation: "大头针数据模型",其实叫什么都可以,只不过这个类遵循了大头针数据模型必须遵循的一个协议MKAnnotation
            //验证当前的userLocation,对应的大头针视图就是我们看到的蓝点
            //coordinate: CLLocationCoordinate2D确定当前大头针插在哪个位置
            userLocation.title = "大哥"
            userLocation.subtitle = "打你"
            print("location:\(userLocation.coordinate)")
            
            //2.调整地图中心(显示用户的位置信息后,通过控制地图的中心坐标来不断跟随用户位置)
            //效果:只是调整地图的显示中心,但不会自动放大地图
            mapView.setCenter(userLocation.coordinate, animated: true)
            
            //3、设置地图显示区域
            //区域region(包括中心(center)和跨度(span))
            //跨度:1.经度跨度(地图视图的宽所占据的经度) 2.纬度跨度(地图视图的高所占据的纬度)
            //经纬度跨度越小,我们看到的地图越详细
            let center: CLLocationCoordinate2D = (userLocation.location?.coordinate)!
            let span: MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.012700175462356356, longitudeDelta: 0.0083434505961861305)
            let region: MKCoordinateRegion = MKCoordinateRegion(center: center, span: span)
            mapView.setRegion(region, animated: true)
        }
        
        //区域改变时调用
        func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            //在这个方法里我们手动的放大区域,来寻找合适的跨度设置到上一个方法中的经纬度跨度
            print(mapView.region.span)
        }
    }
    

    四、大头针的基本使用

    1、增加一个大头针数据模型

    增加一个大头针数据模型

    2、点击屏幕view时移除mapView所有大头针

    点击屏幕view时移除mapView所有大头针

    代码:

    ---------------------------自定义一个大头针数据模型---------------------------
    import UIKit
    import MapKit
    
    class WXAnnotation: NSObject,MKAnnotation {
        //去掉大头针在地图上的位置
        var coordinate: CLLocationCoordinate2D
        //点击大头针弹框标题
        var title: String?
        //点击大头针弹框子标题
        var subtitle: String?
        init(coordinate: CLLocationCoordinate2D,title: String?,subtitle: String?){
            self.coordinate = coordinate
            self.title = title
            self.subtitle = subtitle
        }
    }
    ----------------------------ViewController.swift--------------------------
    import UIKit
    import MapKit
    
    //MVC
    //操作大头针视图,实际就是操作的大头针数据模型
    //添加一个大头针视图,就是添加一个大头针数据模型
    //删除一个大头针视图,就是删除一个大头针数据模型
    class ViewController: UIViewController {
        
        lazy var locationM: CLLocationManager = {
            let locationM = CLLocationManager()
            return locationM
        }()
        
        @IBOutlet weak var mapView: MKMapView!
        override func viewDidLoad() {
            super.viewDidLoad()
            //请求定位授权
            if #available(iOS 8.0, *) {
                locationM.requestAlwaysAuthorization()
            }
            mapView.delegate = self
    //        mapView.showsUserLocation = true
            mapView.userTrackingMode = .followWithHeading;
        }
    }
    
    extension ViewController: MKMapViewDelegate {
        /**获取用户位置信息
       * mapView 地图视图
       * userLocation 大头针数据模型
       */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //1.创建一个大头针数据模型
            let annotation:WXAnnotation = WXAnnotation(coordinate: (userLocation.location?.coordinate)!, title: "你好", subtitle: "hello world")
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
        }
        
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //3.移除大头针数据模型(可以移除一个或所有大头针)
                    mapView.removeAnnotations(mapView.annotations)
        }
    }
    

    3、大头针的使用场景

    点击mapView时添加一个大头针,弹框时显示城市名称

    点击mapView时添加一个大头针,弹框时显示城市名称
    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var mapView: MKMapView!
        lazy var locationM: CLLocationManager = {
            let locationM = CLLocationManager()
            return locationM
        }()
        
        //地理编码和反地理编码的类
        lazy var geoCoder:CLGeocoder = {
            let geoCoder = CLGeocoder()
            return geoCoder
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //请求定位授权
            if #available(iOS 8.0, *) {
                locationM.requestAlwaysAuthorization()
            }
            mapView.delegate = self
            //        mapView.showsUserLocation = true
            mapView.userTrackingMode = .followWithHeading;
        }
    }
    
    extension ViewController: MKMapViewDelegate {
        /**获取用户位置信息
         * mapView 地图视图
         * userLocation 大头针数据模型
         */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //1.创建一个大头针数据模型
            let annotation:WXAnnotation = WXAnnotation(coordinate: (userLocation.location?.coordinate)!, title: "你好", subtitle: "hello world")
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
        }
        
        //点击地图添加大头针
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //1.获取当前手指点击对应的经纬度
            //触摸点在mapView上的位置,以mapView左上角为坐标原点
            let point = touches.first?.location(in: mapView)
            //从哪个视图上转换点坐标->经纬度坐标
            let coordinate = mapView.convert(point!, toCoordinateFrom: mapView)
            //2、调用添加大头针的方法
            let annotation = addAnnotation(coordinate: coordinate, title: "nihao", subTitle: "shijie")
            let location: CLLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
            //反地理编码
            geoCoder.reverseGeocodeLocation(location) {(pls, error) in
                if error == nil{
                    let pl = pls?.first
                    annotation.title = pl?.locality
                    annotation.subtitle = pl?.name
                }
            }
            
        }
        
        func addAnnotation(coordinate:CLLocationCoordinate2D,title: String? ,subTitle: String?) -> WXAnnotation {
            //1.创建一个大头针数据模型
            let annotation: WXAnnotation = WXAnnotation(coordinate: coordinate, title: title, subtitle: subTitle)
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
            return annotation
        }
    }
    

    4、自定义大头针,模拟系统实现

    自定义大头针,模拟系统实现
    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var mapView: MKMapView!
        lazy var locationM: CLLocationManager = {
            let locationM = CLLocationManager()
            return locationM
        }()
        
        //地理编码和反地理编码的类
        lazy var geoCoder:CLGeocoder = {
            let geoCoder = CLGeocoder()
            return geoCoder
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //请求定位授权
            if #available(iOS 8.0, *) {
                locationM.requestAlwaysAuthorization()
            }
            mapView.delegate = self
                    mapView.showsUserLocation = true
    //        mapView.userTrackingMode = .followWithHeading;
        }
        
        //点击地图添加大头针
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //1.获取当前手指点击对应的经纬度
            //触摸点在mapView上的位置,以mapView左上角为坐标原点
            let point = touches.first?.location(in: mapView)
            //从哪个视图上转换点坐标->经纬度坐标
            let coordinate = mapView.convert(point!, toCoordinateFrom: mapView)
            //2、调用添加大头针的方法
            let annotation = addAnnotation(coordinate: coordinate, title: "nihao", subTitle: "shijie")
            let location: CLLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
            //反地理编码
            geoCoder.reverseGeocodeLocation(location) {(pls, error) in
                if error == nil{
                    let pl = pls?.first
                    annotation.title = pl?.locality
                    annotation.subtitle = pl?.name
                }
            }
        }
        
        func addAnnotation(coordinate:CLLocationCoordinate2D,title: String? ,subTitle: String?) -> WXAnnotation {
            //1.创建一个大头针数据模型
            let annotation: WXAnnotation = WXAnnotation(coordinate: coordinate, title: title, subtitle: subTitle)
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
            return annotation
        }
    }
    
    
    
    extension ViewController: MKMapViewDelegate {
        /**获取用户位置信息
         * mapView 地图视图
         * userLocation 大头针数据模型
         */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //1.创建一个大头针数据模型
            let annotation:WXAnnotation = WXAnnotation(coordinate: (userLocation.location?.coordinate)!, title: "你好", subtitle: "hello world")
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
        }
        
        /**模型
       *如果我们添加一个大头针数据模型,系统会调用一个方法查找对应的大头针视图显示到地图上;如果这个方法没有实现或者返回为nil,那么系统就会使用默认的大头针视图显示到地图上
       * mapView 地图视图
       * annotation 大头针数据模型
       * 返回值是大头针视图
       */
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            //模拟系统的实现方案
            //MKPinAnnotationView 系统大头针视图对应的类
            //大头针其实是有一个“循环利用机制”
            
            //1.先从缓存池里获取大头针视图
            let identifier = "pin"
            var annotationView: MKPinAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
            
            //2.如果没有获取到,自己创建
            if annotationView == nil {
                annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            }
            //3.对大头针视图进行赋值(这步操作非常重要)
            annotationView?.annotation = annotation
            //3.1.设置大头针参数
            if #available(iOS 9.0, *) {
                annotationView?.pinTintColor = UIColor.red
            }
            //3.2.设置弹框
            annotationView?.canShowCallout = true
            //3.3.设置下落动画
            annotationView?.animatesDrop = true
            //4.返回大头针视图
            return annotationView
        }
    }
    

    5、自定义大头针和弹框

    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var mapView: MKMapView!
        lazy var locationM: CLLocationManager = {
            let locationM = CLLocationManager()
            return locationM
        }()
        
        //地理编码和反地理编码的类
        lazy var geoCoder:CLGeocoder = {
            let geoCoder = CLGeocoder()
            return geoCoder
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //请求定位授权
            if #available(iOS 8.0, *) {
                locationM.requestAlwaysAuthorization()
            }
            mapView.delegate = self
    //                mapView.showsUserLocation = true
            mapView.userTrackingMode = .followWithHeading;
        }
        
        //点击地图添加大头针
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //1.获取当前手指点击对应的经纬度
            //触摸点在mapView上的位置,以mapView左上角为坐标原点
            let point = touches.first?.location(in: mapView)
            //从哪个视图上转换点坐标->经纬度坐标
            let coordinate = mapView.convert(point!, toCoordinateFrom: mapView)
            //2、调用添加大头针的方法
            let annotation = addAnnotation(coordinate: coordinate, title: "nihao", subTitle: "shijie")
            let location: CLLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
            //反地理编码
            geoCoder.reverseGeocodeLocation(location) {(pls, error) in
                if error == nil{
                    let pl = pls?.first
                    annotation.title = pl?.locality
                    annotation.subtitle = pl?.name
                }
            }
        }
        
        func addAnnotation(coordinate:CLLocationCoordinate2D,title: String? ,subTitle: String?) -> WXAnnotation {
            //1.创建一个大头针数据模型
            let annotation: WXAnnotation = WXAnnotation(coordinate: coordinate, title: title, subtitle: subTitle)
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
            return annotation
        }
    }
    
    
    
    extension ViewController: MKMapViewDelegate {
        /**获取用户位置信息
         * mapView 地图视图
         * userLocation 大头针数据模型
         */
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            //1.创建一个大头针数据模型
            let annotation:WXAnnotation = WXAnnotation(coordinate: (userLocation.location?.coordinate)!, title: "你好", subtitle: "hello world")
            //2.添加一个大头针数据模型
            mapView.addAnnotation(annotation)
        }
        
        /**模型
       *如果我们添加一个大头针数据模型,系统会调用一个方法查找对应的大头针视图显示到地图上;如果这个方法没有实现或者返回为nil,那么系统就会使用默认的大头针视图显示到地图上
       * mapView 地图视图
       * annotation 大头针数据模型
       * 返回值是大头针视图
       */
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            
            //1.如果想要自定义大头针视图,要不使用MKAnnotationView,要不就是使用自定义的子类
            //2.如果使用了自定义视图,那么几乎所有的东西都需要我们自己设置
            let identifier = "pin"
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
            if annotationView == nil{
                annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            }
            annotationView?.annotation = annotation
            //1.设置大头针视图的图片
            annotationView?.image = UIImage(named: "category_2.png")
            //2.设置弹框
            annotationView?.canShowCallout = true
            //3.设置大头针视图的偏移量
            annotationView?.centerOffset = CGPoint(x: 10, y: 10)
            //4.控制弹框的偏移量
            annotationView?.calloutOffset = CGPoint(x: -20, y: 20)
            //5.设置弹框的左侧内容(左侧ImageView和右侧ImageView要单独设置,不能共用一个)
            let imageV1: UIImageView = UIImageView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
            imageV1.image = UIImage(named: "htl.jpeg")
            annotationView?.leftCalloutAccessoryView = imageV1
            //6.设置弹框的右侧内容
            let imageV2: UIImageView = UIImageView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
            imageV2.image = UIImage(named: "huba.jpeg")
            annotationView?.rightCalloutAccessoryView = imageV2
            //7.设置详情视图
            if #available(iOS 9.0, *) {
                annotationView?.detailCalloutAccessoryView = UISwitch()
            }
            return annotationView
        }
    }
    
    材料

    相关文章

      网友评论

          本文标题:地图和定位(四)

          本文链接:https://www.haomeiwen.com/subject/hhuoiqtx.html