有没有办法通过
MKMultiPolylineRenderer
使用每条折线的属性?
或者我是否必须创建不同的渲染器,即使唯一的区别是线宽?
我尝试对
MKMultiPolylineRenderer
进行子分类,但无论如何我都看不到将属性与正在绘制的 CGPath
联系起来。
在下面的代码中,
draw(mapRect:zoomScale:in:)
显示我有1197条折线,但是strokePath(in:)
每次绘制调用仅调用一次。
如果我能以某种方式知道它正在抚摸哪个路径号,我可以将属性绑定到中风路径函数。由于 draw(mapRect:) 只绘制一条路径,所以我不知道该怎么做。如果中风路径只提供一个索引我就准备好了。
我想我可以完全重写绘制函数(而不是调用它的超级函数),但我会渲染所有 1197 条路径 1197 次,因为我不知道每次调用渲染的是什么路径。
class MyMultiPolylineRenderer: MKMultiPolylineRenderer {
//Even though there are 1197 polylines, this is called once per draw(mapRect:)
override func strokePath(_ path: CGPath, in context: CGContext) {
super.strokePath(path, in: context)
print("strokePath")
}
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
//Causes a single call to strokePath
super.draw(mapRect, zoomScale: zoomScale, in: context)
var counter = 0
for poly in self.multiPolyline.polylines {
counter += 1
}
//polylines counter: 1197
print("polylines counter: \(counter)")
}
}
首先我们需要一条对其颜色有意见的折线
class ColoredPolyline: MKPolyline {
var strokeColor: UIColor?
}
让我们创建一些测试数据: 从圣家堂到蓝色博物馆的蓝色直线 还有一条从圣家堂到玛丽蒂姆博物馆的黄色直线:
func createTestColoredMultiPolyline() -> MKMultiPolyline {
let sagradaFamília = CLLocationCoordinate2D(latitude: 41.4035944, longitude: 2.1743616)
let museuBlau = CLLocationCoordinate2D(latitude: 41.41103109073135, longitude: 2.221040725708008)
let museuMaritim = CLLocationCoordinate2D(latitude: 41.37546408659406, longitude: 2.1759045124053955)
let toBlauCoordinates = [sagradaFamília, museuBlau]
let polylineToMuseuBlau = ColoredPolyline(coordinates: toBlauCoordinates, count: toBlauCoordinates.count)
polylineToMuseuBlau.strokeColor = UIColor.blue
let toMaritimCoordinates = [sagradaFamília, museuMaritim]
let polylineToMuseuMaritim = ColoredPolyline(coordinates: toMaritimCoordinates, count: toMaritimCoordinates.count)
polylineToMuseuMaritim.strokeColor = UIColor.yellow
let testMultiPolyline = MKMultiPolyline([polylineToMuseuBlau, polylineToMuseuMaritim])
return testMultiPolyline
}
请注意,如果您将这些多段线绘制在彼此之上,这些多段线的顺序很重要。
现在让我们编写一个尊重
MKMultiPolylineRenderer
颜色的 ColoredPolyline
(并在其他情况下使用 MKMultiPolylineRenderer
的颜色):
class MultiColorMultipolylinerenderer: MKMultiPolylineRenderer {
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
let roadWidth = MKRoadWidthAtZoomScale(zoomScale)
/// if oloylines draw on top of each other the creator of self.multiPolyline is responsible for the correct sequence
let polylines = self.multiPolyline.polylines
context.saveGState()
for polyline in polylines {
// ger coordinates of polyline
let polylineMapPoints = polyline.coordinates.map { coord in
MKMapPoint(coord)
}
guard polylineMapPoints.count > 0 else {
continue
}
let coloredPolyline = polyline as? ColoredPolyline
// usually all polylines in a MultiColorMultipolylinerenderer are rendered with the same self.strokeColor
// but we let ColoredPolyline have its own opinion
let polylineStrokeColor = coloredPolyline?.strokeColor ?? self.strokeColor ?? UIColor.label
// stroke properties to context
context.setBlendMode(CGBlendMode.exclusion)
context.setStrokeColor(polylineStrokeColor.cgColor)
if self.lineWidth > 0 {
context.setLineWidth(self.lineWidth*roadWidth)
} else {
context.setLineWidth(roadWidth)
}
context.setLineJoin(self.lineJoin)
context.setLineCap(self.lineCap)
context.setMiterLimit(self.miterLimit)
// create path
context.move(to: self.point(for: polylineMapPoints[0]))
for element in 1 ..< polyline.pointCount {
let point_ = self.point(for: polylineMapPoints[element])
context.addLine(to: point_)
}
// draw previously created path
context.drawPath(using: .stroke)
}
context.restoreGState()
}
}
该代码使用了一个小助手:
public extension MKMultiPoint {
var coordinates: [CLLocationCoordinate2D] {
var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid, count: pointCount)
getCoordinates(&coords, range: NSRange(location: 0, length: pointCount))
return coords
}
}
这是测试数据在我的游客应用程序中的样子: