我需要一个自定义的MKOverlay描边样式。 我需要在覆盖层内部使用更宽的浅色,就像这个笔触一样。
我知道怎么画它,
class PolygonRenderer:MKPolygonRenderer {
override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) {
let fullPath = CGPathCreateMutable()
for i in 0 ..< self.polygon.pointCount {
let point = self.pointForMapPoint(self.polygon.points()[i])
print(point)
if i == 0 {
CGPathMoveToPoint(fullPath, nil, point.x, point.y)
} else {
CGPathAddLineToPoint(fullPath, nil, point.x, point.y)
}
}
let baseWidth = 10 / zoomScale
CGContextAddPath(context, self.path)
CGContextSetStrokeColorWithColor(context, UIColor.blueColor().colorWithAlphaComponent(0.3).CGColor)
CGContextSetLineWidth(context, baseWidth * 2)
CGContextSetLineCap(context, self.lineCap)
CGContextStrokePath(context);
CGContextAddPath(context, self.path)
CGContextSetStrokeColorWithColor(context, UIColor.blueColor().CGColor)
CGContextSetLineWidth(context, baseWidth)
CGContextSetLineCap(context, self.lineCap)
CGContextStrokePath(context)
}
}
是否可以像第一张图像一样绘制路径?
答案 0 :(得分:1)
对于那些可能会发现这个问题有用的人,我找到了一种方法来做到这一点。此过程适用于仅包含点的CGPath,即它不包含弧。所以这里是我创建的MKPolygonRender子类。
import UIKit
import MapKit
extension CGPoint {
func angleToPoint(comparisonPoint: CGPoint) -> CGFloat {
let originX = comparisonPoint.x - self.x
let originY = comparisonPoint.y - self.y
let bearingRadians = atan2f(Float(originY), Float(originX))
var bearingDegrees = CGFloat(bearingRadians).degrees
while bearingDegrees < 0 {
bearingDegrees += 360
}
return (bearingDegrees + 270).truncatingRemainder(dividingBy: 360)
}
}
extension CGFloat {
var degrees: CGFloat {
return self * CGFloat(180.0 / M_PI)
}
}
class PolygonRenderer: MKPolygonRenderer {
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
let strokeWidth = MKRoadWidthAtZoomScale(zoomScale) * self.lineWidth
let outerPath = CGMutablePath()
let innerPath = CGMutablePath()
var previousPoint = point(for: self.polygon.points()[self.polygon.pointCount - 1])
for i in 0 ..< self.polygon.pointCount {
let currentPoint = point(for: self.polygon.points()[i])
let nextPoint:CGPoint = point(for: self.polygon.points()[(i + 1) % self.polygon.pointCount])
let a : CGFloat = {
let lengthA = distance(currentPoint, b: nextPoint)
let lengthB = distance(previousPoint, b: currentPoint)
let lengthC = distance(nextPoint, b: previousPoint)
return CGFloat(Int(round(Double(angle(lengthA, b: lengthB, c: lengthC)))))
}()
let degrees = previousPoint.angleToPoint(comparisonPoint: currentPoint)
let strokeHyp: CGFloat = CGFloat(strokeWidth) / CGFloat(sind(Double(a) / 2))
var newPoint = CGPoint()
newPoint.x = CGFloat(Double(strokeHyp) * cos(degreesToRadians(Double(degrees + (360 - (a / 2))).truncatingRemainder(dividingBy: 360)))) + currentPoint.x
newPoint.y = CGFloat(Double(strokeHyp) * sin(degreesToRadians(Double(degrees + (360 - (a / 2))).truncatingRemainder(dividingBy: 360)))) + currentPoint.y
print("stroke width: ", strokeWidth, "stroke hyp: ", strokeHyp)
print("pointIndex: ", i,"dir: ", degrees)
if i == 0 {
outerPath.move(to: currentPoint)
innerPath.move(to: newPoint)
} else {
outerPath.addLine(to: currentPoint)
innerPath.addLine(to: newPoint)
}
previousPoint = currentPoint
}
outerPath.closeSubpath()
context.addPath(outerPath)
context.setLineWidth(strokeWidth)
context.setStrokeColor(self.strokeColor?.cgColor ?? UIColor.black.cgColor)
context.strokePath()
innerPath.closeSubpath()
context.addPath(innerPath)
context.setLineWidth(strokeWidth)
context.setStrokeColor(self.strokeColor?.withAlphaComponent(0.3).cgColor ?? UIColor.black.withAlphaComponent(0.3).cgColor)
context.strokePath()
}
func angle(_ a:CGFloat, b:CGFloat, c:CGFloat) -> CGFloat {
var angle = (a * a) + (b * b) - (c * c)
angle = angle / (2 * a * b)
return CGFloat(radiansToDegrees(acos(Double(angle))))
}
func distance(_ a:CGPoint,b:CGPoint)->CGFloat{
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
func direction(_ center:CGPoint,point:CGPoint)->CGFloat{
let hyp = Double(distance(center, b: point))
let adj = Double(center.y - point.y)
var angle = CGFloat(radiansToDegrees(asin(adj/hyp)))
if point.x < center.x {
angle += 180
} else {
angle = 360 - angle
}
return round(angle)
}
func radiansToDegrees(_ radians:Double)->Double{
return (radians * 180.0 / Double.pi)
}
func degreesToRadians(_ degrees:Double)->Double{
return ((degrees - 90) * Double.pi / 180.0)
}
func sind(_ degrees: Double) -> Double {
return __sinpi(degrees/180.0)
}
}