Reputation: 4202
Is there a way to add a border to a polyline in apple mapview?
P.S
Just wanna share a solution
Upvotes: 0
Views: 822
Reputation: 3303
public class BorderPathRenderer: MKOverlayPathRenderer {
var polyline: MKPolyline
var color: UIColor
var showsBorder: Bool = false
var borderColor: UIColor = .black
public init(polyline: MKPolyline, color: UIColor) {
self.polyline = polyline
self.color = color
super.init(overlay: polyline)
}
public init(polyline: MKPolyline, color: UIColor, showsBorder: Bool, borderColor: UIColor) {
self.polyline = polyline
self.color = color
self.showsBorder = showsBorder
self.borderColor = borderColor
super.init(overlay: polyline)
}
public override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
let baseWidth: CGFloat = lineWidth / zoomScale
if showsBorder {
context.setLineWidth(baseWidth * 2)
context.setLineJoin(CGLineJoin.round)
context.setLineCap(CGLineCap.round)
context.addPath(path)
context.setStrokeColor(borderColor.cgColor)
context.strokePath()
}
context.setLineWidth(baseWidth)
context.addPath(path)
context.setStrokeColor(color.cgColor)
context.strokePath()
super.draw(mapRect, zoomScale: zoomScale, in: context)
}
public override func createPath() {
let path: CGMutablePath = CGMutablePath()
var pathIsEmpty: Bool = true
for i in 0...self.polyline.pointCount - 1 {
let point: CGPoint = self.point(for: self.polyline.points()[i])
if pathIsEmpty {
path.move(to: point)
pathIsEmpty = false
} else {
path.addLine(to: point)
}
}
self.path = path
}
}
Upvotes: 1
Reputation: 4202
My implementation is to add another polyline overlay underneath the main one that will have a lineWidth
a few pixels thicker (your border width we can say) than the main one.
// Instantiate the main polyline
let polylineObj = MKPolyline(coordinates: yourArrayOfCoords, count: yourArrayOfCoords.count)
// Identifier to tell which is which
polylineObj.title = "main"
// Instantiate the border polyline
let borderPolylineObj = MKPolyline(coordinates: yourArrayOfCoords, count: yourArrayOfCoords.count)
// Add main polyline
appleMapView.addOverlay(polylineObj)
// Add border polyline below the main polyline
appleMapView.insertOverlay(borderPolylineObj, below: polylineObj)
Then on the MKMapViewDelegate
function:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
// Use different colors for the border and the main polyline
renderer.strokeColor = overlay.title == "main" ? .blue : .red
// Make the border polyline bigger. Their difference will be like the borderWidth of the main polyline
renderer.lineWidth = overlay.title == "main" ? 4 : 6
// Other polyline customizations
renderer.lineCap = .round
renderer.lineJoin = .bevel
return renderer
}
P.S
If you have a better implementation please do answer. This implementation is expensive to do as this will essentially double the number of polyline being rendered.
Upvotes: 3