如何在MKMapView上使用MKOverlayView绘制圆弧/曲线线

问题描述 投票:14回答:3

现在需要帮助。我可以使用MKPolyline和MKPolylineView绘制线,但是如何在MKMapView的两个坐标之间绘制圆弧或曲线呢?非常感谢。

最终解决方案

最后我在这里写下这些结论,以帮助想要的人。

如果您想:

  1. 仅在地图上绘制弧形路径
  2. 仅在地图上绘制图像
  3. 组合弧形路径和图像作为地图上的叠加层

所以解决方案是:

  1. MKPolylineMKPolylineView绘制线条,MKPolygonMKPolygonView绘制多边形,MKCircleMKCircleView绘制圆。没有人适合吗?弧线在哪里?哦是的现在,真正的解决方案是:创建一个从MKOverlayPathView派生的自定义类,并覆盖-createPath方法,在-createPath中创建一个使用CGContextAddArcToPoint或其他函数的弧例如,并将您刚创建的路径与MKOverlayPathView的path属性相关联,即可完成自定义工作。然后在地图中添加MKPolyline(是的!只需MKPolyline!),然后在-mapView:viewForOverlay:方法中创建自定义类,并采用该折线。然后,只要运行它,一切就可以按您期望的方式运行。魔法?您可以将MKPolyline绘制为弧!
  2. 只是图像?使用MKAnnotationView。大功告成!你能行的!我相信!
  3. 在我的问题中,我想用叠加层中的图像绘制圆弧。因此,我创建了一个符合MKOverlay协议的自定义类,并创建了一个由MKOverlayView派生的自定义类来绘制该覆盖图。一切正常,但我无法在地图上绘制任何路径!我已经将lineWidth设置为1,2,3,4 ...但是这行不通!嗯..解决方案是通过MKRoadWidthAtZoomScale(zoomScale)函数设置线宽的,您可以看到路径!完成了...

以及此处的一些提示:

  1. 使用核心图形绘制路径,而不是MapKit坐标或UIView坐标!
  2. 在CG函数中,请记住,线宽应通过此函数转换:MKRoadWidthAtZoomScale(zoomScale)
  3. 希望帮助
iphone ios ipad mapkit mkmapview
3个回答
1
投票

阅读文档,似乎您可以创建MKOverlayPathView的实例并将任意CGPathRef对象分配给其path属性。该路径可以同时包含直线和圆弧。

我不知道(并且文档中没有提到)路径的坐标应采用哪种格式(想到的是MKMapPointCLLocationCoordinate2D),但是您可以通过尝试一下来找到答案。


1
投票

[您已经在评论中回答了自己,但是我想向所有人指出GitHub上出色的AIMapViewWrapper项目,其中包括sample code,用于在一组坐标上绘制弧形路径。在该项目中,它被用于绘制平面所走的路径,包括其下方的阴影路径(以及其他诸如沿该路径为平面动画等内容)的路径。对于任何对此采取刺伤的人都应该派上用场。


0
投票

在回答问题之前,重要的是要提到MKOverlayView已过时,并且从iOS7开始,以后我们应该使用MKOverlayRenderer

在iOS 7及更高版本中,请使用MKOverlayRenderer类来显示叠加层。

我们现在可以按照实现弧/曲线的方式对其进行细分:

  1. 首先,我们需要定义并添加多边形线。让我们创建一个具有2个坐标的地方:
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(polyline)
  1. 添加折线后,MKMapView希望我们提供与在第1节创建的MKOverlayRenderer相对应的适当MKPolyline。我们需要的method是:

mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer

基本上是:

向委托指定渲染器对象,以在绘制指定的叠加层时使用。

  1. 所以让我们提供该对象。我们将希望继承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
}

我们基本上完成了。您可能需要考虑添加宽度/笔划/颜色等,所以您可以参见曲线

  1. ((可选)如果您对渐变曲线感兴趣,这是一个非常好的解决方案here,但是您必须在代码中进行2项更改才能使它起作用:]
  2. 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不同:

...

not

包括贝塞尔曲线和二次曲线的控制点。希望有所帮助:)
© www.soinside.com 2019 - 2024. All rights reserved.