地图和定位(四)

2020-03-07  本文已影响0人  weyan

一、地图的基本使用(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
    }
}
材料
上一篇下一篇

猜你喜欢

热点阅读