繁体   English   中英

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

[英]How to draw arc/curve line with MKOverlayView on MKMapView

现在需要帮助。 我可以用 MKPolyline 和 MKPolylineView 画线,但是如何在 MKMapView 上的两个坐标之间画弧线或曲线? 万分感谢。

您已经在评论中回答了自己,但我想向大家指出 GitHub 上优秀的AIMapViewWrapper项目,其中包括用于在一组坐标上绘制圆弧路径的示例代码 在那个项目中,它被用来绘制平面所采用的路径,包括它下面的阴影路径(以及其他东西,例如沿该路径为平面设置动画)。 任何人都应该派上用场。

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

我不知道(并且文档没有提到)路径的坐标应该是什么格式( MKMapPointCLLocationCoordinate2D ),但您可能可以通过一些试验找到MKMapPoint

在回答这个问题之前,重要的是要提到MKOverlayView已被弃用,并且从 iOS7 和更高版本开始,我们应该使用MKOverlayRenderer

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

我们现在可以将其分解为如何实现圆弧/曲线线:

  1. 首先,我们需要定义并添加我们的多边形线。 让我们用 2 个坐标创建一个:
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(polyline)
  1. 添加折线后, MKMapView会要求我们提供一个合适的MKOverlayRenderer对应于我们在第 1 部分创建的MKPolyline 。我们需要的方法是:

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. (可选)如果您对渐变曲线感兴趣,这里有一个非常好的解决方案但您必须在代码中进行 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不同:

...包括贝塞尔曲线和二次曲线的控制点。

希望有帮助:)

如果你想:

  1. 只需在地图上绘制弧形路径
  2. 只需在地图上绘制图像
  3. 将圆弧路径和图像组合为地图上的叠加

所以解决办法是:

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

还有一些提示:

  1. 使用 Core Graphic 绘制路径,而不是 MapKit 坐标或 UIView 坐标!
  2. 在 CG 函数中,请记住应通过此函数转换线宽: MKRoadWidthAtZoomScale(zoomScale)
  3. 希望有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM