这里主要说iOS原生地图
iOS原生地图很有意思,在国内是用的高德地图,在国外才是苹果地图~
就比如在国内你在手机上看国外地图,非常不详细,和国内街道、景观的详尽程度不可同日而语
一、MapKit里的MKMapView的一些主要属性和方法
/** 是否可以旋转 */
var isRotateEnabled: Bool { get set}
/** 是否可以捏和 */
var isPitchEnabled: Bool { get set}
/** 是否显示指南针 */
var showsCompass: Bool { get set}
/** 显示定位 */
var showsUserLocation: Bool { get set}
/** 地图类型 */
var mapType: MKMapType { get set}
/** 显示区域 */
var region: MKCoordinateRegion { get set}
/** 中心点 */
var centerCoordinate: CLLocationCoordinate2D { get}
/** 设置显示区域 */
func setRegion(_ region: MKCoordinateRegion, animated: Bool)
/** 坐标转经纬度 */
func convert(_ point: CGPoint, toCoordinateFrom view: UIView?) -> CLLocationCoordinate2D
/** 经纬度转坐标 */
func convert(_ coordinate: CLLocationCoordinate2D, toPointTo view: UIView?) -> CGPoint
代理方法
/** 自定义标记点入口 */
(nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
/** 自定义曲线入口 */
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer;
/** 地图显示区域改变 */
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool);
二、自定义标记点Annotation
1、自定义class: CustomAnnotation: MKPointAnnotation
可以在里面添加一些自定义属性,该类可以理解为标记点的model
class CustomAnnotation: MKPointAnnotation {
var index: Int = 0
var annotationID: String?
var title: String?
...
}
同时自定义class: CustomAnnotationView: MKAnnotationView
可以在里面自定义控件,该类可以理解为标记点View
class CustomAnnotationView: MKAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
///自定义控件入口
}
override var annotation: MKAnnotation? {
didSet {
///可以在这里去为自定义的控件填充数据
}
}
...
}
Annotation的增删改查API
///增
open func addAnnotation(_ annotation: MKAnnotation)
open func addAnnotations(_ annotations: [MKAnnotation])
///删
open func removeAnnotation(_ annotation: MKAnnotation)
open func removeAnnotations(_ annotations: [MKAnnotation])
///查
open var annotations: [MKAnnotation] { get }
///修改位置(如果要修改数据,只需自己添加入口即可)
open var coordinate: CLLocationCoordinate2D
然后,将Annotation和AnnotationView绑定起来
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is CustomAnnotation {
let identifier = "CustomAnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? CustomAnnotationView
if annotationView == nil {
annotationView = CustomAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
return annotationView
}
...
}
这样就完成了一个自定义标记点,因为要自定义两个类,要去添加Annotation,还要在代理方法里绑定,流程很是繁琐,所以可以抽象封装一下
封装后简单的Annotation只需:
let options = AutelAnnotationOptions(coordinate: coordinate, "Img_map_mark".toImage(), nil, false)
let annotation = mapView.createAnnotation(options, nil)
mapView.addAnnotation(annotation)
*****************************************************************************************************
init(coordinate coord: CLLocationCoordinate2D, _ defaultImage: UIImage? = nil, _ selectedImage: UIImage? = nil, _ gestureEnabled: Bool = false)
func createAnnotation(_ options: AutelAnnotationOptions?, _ customView: AutelCustomAnnotationView?) -> AutelAnnotation
如果项目中地图占比较重,就非常有封装的必要性,具体怎么封装这里就不再说了
三、绘制线:直线、圆、多边形、自定义曲线
1.绘制直线
自定义class,CustomLine: MKPolyline
class CustomLine: MKPolyline {
var strokeColor = UIColor.red
var width: CGFloat = 5
}
添加线段到地图上
let line = CustomLine(coordinates:[coor1,coor2], count: 2)
line.strokeColor = .green
line.width = 10
mapView.addOverlay(line, level: .aboveRoads)
代理方法里设置MKPolylineRenderer
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let line = overlay as? CustomLine {
let render:MKPolylineRenderer = MKPolylineRenderer(polyline: line)
render.lineWidth = line.width
render.strokeColor = line.strokeColor
return render
}
...
}
这样就完成了一条线段的绘制
如果想要自定义曲线呢?比如绘制贝塞尔曲线,曲线上加箭头等等
只需要自定义CustomLineRenderer: MKPolylineRenderer
重写其draw方法即可
override func draw(_ mapRect: MKMapRect,
zoomScale: MKZoomScale,
in context: CGContext) {
...
}
2.绘制圆、多边形
自定义class,CustomCircle: MKCircle
class CustomPolygon : MKPolygon
添加到地图上
let circle = CustomCircle(center: center, radius: radius)
mapView.addOverlay(circle)
let polygon = CustomPolygon.init(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(polygon)
在代理方法里设置render
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = super.mapView(mapView, rendererFor: overlay)
if let overlay = overlay as? CustomCircle {
let render = MKCircleRenderer.init(circle: overlay)
render.strokeColor = UIColor.red
render.lineWidth = 1
return render
} else if let overlay = overlay as? CustomPolygon {
let render: MKPolygonRenderer = MKPolygonRenderer.init(polygon: overlay)
render.fillColor = UIColor.blue
return render
}
}
这样就完成了圆、多边形的绘制
同样,绘制曲线尤其是自定义曲线也比较繁琐,需要两个自定义类,添加曲线代码,代理方法设置,四个地方都要写...所以,如果地图在项目中比重比较重,也很有必要抽象封装一下
let options = AutelCircleOptions(center: coordinate, radius: radius)
options.strokeColor = UIColor.blue
options.lineWidth = 2
let circle = mapView.createCircle(options, custom: nil)
mapView.addOverlay(circle)