我正在开发一个请求多个路线的应用程序(MKDirectionsRequest)并在mapView中绘制路线,一切正常。
但是我遇到了一个问题:我想用不同的颜色绘制每条路线。
第一个想法很简单:使用标题/副标题来“标记”不同的MKPolyline,这样我就可以在委托函数中设置我想要的颜色:
mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
但是我不喜欢这个解决方案,因为它“丑陋”,我将不得不解析一个字符串,我必须通过不同的params(流量..)
第二个简单的解决方案是继承MKPolyline,简单就是.. 由于MKPolyline没有指定的初始化程序,这是不可能的(是吗?)
[编辑]:我想创建一个MKPolyline的子类来复制“on it”已经创建的MKDirectionsRequest.routes返回的MKPolyline但我无法弄清楚如何覆盖只读参数(Apple说我们应该在子类中重写它们并添加setter,但是我在setter中有一个无限循环,女巫是......正常)
如果使用objC,在运行时“注入”代码并添加我的参数很简单,但我使用的是swift。
任何人都可以帮忙,谢谢。
答案 0 :(得分:3)
不需要自定义渲染器的简单方法:
import UIKit
import MapKit
class CustomPolyline : MKPolyline {
var color: UIColor?
}
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// setup mapView
mapView.delegate = self
// set map view region
let location : CLLocationCoordinate2D = CLLocationCoordinate2DMake(51.4987, 0.007);
let viewRegion = MKCoordinateRegionMakeWithDistance(location, 400, 400)
mapView.setRegion(viewRegion, animated:true )
// add red line
let coords1 = [CLLocationCoordinate2D(latitude: 51.499526, longitude: 0.004785),CLLocationCoordinate2D(latitude: 51.500007, longitude: 0.005493)]
let polyline1 = CustomPolyline(coordinates: coords1, count: coords1.count)
polyline1.color = UIColor.red
mapView.add(polyline1)
// add blue line
let coords2 = [CLLocationCoordinate2D(latitude: 51.498103, longitude: 0.007574), CLLocationCoordinate2D(latitude: 51.498190, longitude: 0.009677)]
let polyline2 = CustomPolyline(coordinates: coords2, count: coords2.count)
polyline2.color = UIColor.blue
mapView.add(polyline2)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is CustomPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = (overlay as! CustomPolyline).color
polylineRenderer.lineWidth = 4
return polylineRenderer
}
return MKOverlayRenderer()
}
}
答案 1 :(得分:0)
为什么要为自定义MKOverlay设置颜色,难道你不能简单地将所需的颜色设置为MKOverlayRenderer?那应该很简单。
您也可以轻松地继承MKPolyline。我不明白为什么你不能这样做。
如果您希望能够创建自定义MKOverlay并设置自定义属性,然后将其绘制到地图中,您还需要创建自己的渲染器。这似乎是一项重大工作。但是,这是一个如何做到这一点的例子。
import UIKit
import MapKit
public class CustomOverlay: MKPolyline {
public var customColor: UIColor?
}
public class CustomRenderer: MKPolylineRenderer {
override public func strokePath(_ path: CGPath, in context: CGContext) {
guard let overlayColor = self.overlay as? CustomOverlay, let color = overlayColor.customColor else {
super.strokePath(path, in: context)
return
}
context.saveGState()
context.setStrokeColor(color.cgColor)
context.addPath(path)
context.drawPath(using: .stroke)
context.restoreGState()
}
}
public extension CLLocationCoordinate2D {
static let Salo = CLLocationCoordinate2DMake(60.3909, 23.1355)
static let Turku = CLLocationCoordinate2DMake(60.454510, 22.264824)
static let Helsinki = CLLocationCoordinate2DMake(60.170833, 24.9375)
}
public class ViewController: UIViewController, MKMapViewDelegate {
private var mapView: MKMapView!
override public func viewDidLoad() {
super.viewDidLoad()
createMapView()
setupMapView()
}
private func createMapView() {
mapView = MKMapView(frame: .zero)
mapView.translatesAutoresizingMaskIntoConstraints = false
mapView.delegate = self
view.addSubview(mapView)
[mapView.topAnchor.constraint(equalTo: view.topAnchor),
mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor)].forEach { $0.isActive = true }
}
private func setupMapView() {
let coordinates: [CLLocationCoordinate2D] = [.Helsinki, .Turku]
let customPolyLine = CustomOverlay(coordinates: coordinates, count: coordinates.count)
customPolyLine.customColor = UIColor.red
mapView.add(customPolyLine)
let coordinateSpan = MKCoordinateSpan(latitudeDelta: 3, longitudeDelta: 3)
let region = MKCoordinateRegion(center: .Salo, span: coordinateSpan)
mapView.setRegion(region, animated: true)
}
// MARK: MKMapViewDelegate
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
/* return a simple renderer */
// let renderer = MKPolylineRenderer(overlay:overlay)
// renderer.lineWidth = 2
// renderer.lineDashPattern = [1, 2, 1]
// renderer.strokeColor = UIColor.red
// return renderer
/* a custom renderer */
let customRenderer = CustomRenderer(overlay: overlay)
customRenderer.lineWidth = 2
customRenderer.strokeColor = UIColor.green // this color is not used, since we apply color from overlay inside strokePath(:inContext:) method for custom renderer
customRenderer.lineDashPattern = [1, 2, 1]
return customRenderer
}
}