[英]How to draw arc/curve line with MKOverlayView on MKMapView
现在需要帮助。 我可以用 MKPolyline 和 MKPolylineView 画线,但是如何在 MKMapView 上的两个坐标之间画弧线或曲线? 万分感谢。
您已经在评论中回答了自己,但我想向大家指出 GitHub 上优秀的AIMapViewWrapper项目,其中包括用于在一组坐标上绘制圆弧路径的示例代码。 在那个项目中,它被用来绘制平面所采用的路径,包括它下面的阴影路径(以及其他东西,例如沿该路径为平面设置动画)。 任何人都应该派上用场。
阅读文档,似乎您可以创建MKOverlayPathView
的实例并将任意CGPathRef
对象分配给其path
属性。 该路径可以包含直线和圆弧。
我不知道(并且文档没有提到)路径的坐标应该是什么格式( MKMapPoint
或CLLocationCoordinate2D
),但您可能可以通过一些试验找到MKMapPoint
。
在回答这个问题之前,重要的是要提到MKOverlayView已被弃用,并且从 iOS7 和更高版本开始,我们应该使用MKOverlayRenderer :
在 iOS 7 及更高版本中,请改用 MKOverlayRenderer 类来显示叠加层。
我们现在可以将其分解为如何实现圆弧/曲线线:
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(polyline)
MKMapView
会要求我们提供一个合适的MKOverlayRenderer
对应于我们在第 1 部分创建的MKPolyline
。我们需要的方法是: mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
基本上:
在绘制指定的叠加层时向委托请求渲染器对象。
MKOverlayPathRenderer
这显然继承自MKOverlayRenderer
和文档状态:当您的叠加层的形状由 CGPath 对象定义时,请使用此渲染器。 默认情况下,此渲染器填充叠加层的形状并使用其当前属性表示路径的笔划。
因此,如果我们按原样使用我们新的子类对象,我们将得到一个开箱即用的解决方案,它是从第 1 节中定义的第一个坐标到第二个坐标的实线,但由于我们想要一个曲线,我们将不得不为此重写一个方法:
您可以按原样或子类使用此类来定义其他绘图行为。 如果是子类,则覆盖 createPath() 方法并使用该方法构建适当的路径对象。 要更改路径,请使其无效并使用您的子类获得的任何新数据重新创建路径。
这意味着在我们的CustomObject: MKOverlayPathRenderer
我们将覆盖createPath
:
override func createPath() {
// Getting the coordinates from the polyline
let points = polyline.points()
// Taking the center of the polyline (between the 2 coordiantes) and converting to CGPoint
let centerMapPoint = MKMapPoint(polyline.coordinate)
// Converting coordinates to CGPoint corresponding to the specified point on the map
let startPoint = point(for: points[0])
let endPoint = point(for: points[1])
let centerPoint = point(for: centerMapPoint)
// I would like to thank a co-worker of mine for the controlPoint formula :)
let controlPoint = CGPoint(x: centerPoint.x + (startPoint.y - endPoint.y) / 3,
y: centerPoint.y + (endPoint.x - startPoint.x) / 3)
// Defining our new curved path using Bezier path
let myPath = UIBezierPath()
myPath.move(to: startPoint)
myPath.addQuadCurve(to: endPoint,
controlPoint: controlPoint)
// Mutates the solid line with our curved one
path = myPath.cgPath
}
我们基本上完成了。 您可能需要考虑添加宽度/笔触/颜色等,以便您可以看到曲线。
4.1. 在覆盖override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext)
,就在添加渐变之前,您必须添加第 3 节中的相同代码,但不是更改内部path
而是必须添加它提供的上下文:
context.move(to: startPoint)
context.addQuadCurve(to: endPoint,
control: controlPoint)
这基本上为我们提供了一条关于渐变着色所需的曲线。
4.2. 而不是使用的path.boundingBoxOfPath
我们将需要使用path.boundingBox
因为:
...包括贝塞尔曲线和二次曲线的控制点。
与boundingBoxOfPath
不同:
...不包括贝塞尔曲线和二次曲线的控制点。
希望有帮助:)
如果你想:
所以解决办法是:
还有一些提示:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.