【问题标题】:How to draw arc/curve line with MKOverlayView on MKMapView如何在 MKMapView 上使用 MKOverlayView 绘制弧线/曲线
【发布时间】:2011-04-15 06:53:07
【问题描述】:

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

【问题讨论】:

  • 嗨,我正在尝试使用您的解决方案来在我的地图上绘制圆弧路径,但我遇到了一些问题...您能否给我看一些代码,因为我真的需要在我的应用程序,到目前为止找不到任何解决方法...在此先感谢!本
  • 嗨,@Ben。你想在地图上画什么?
  • 谢谢!当您说:“然后在 -mapView:viewForOverlay: 方法中创建自定义类时,您是什么意思?”我应该这样做:[[THE-CUSTOM-CLASS alloc] initWithOverlay:THE-MKPOLYLINE-OVERLAY]
  • 您能否举例说明被覆盖的 -createPath 方法的外观。不幸的是,我没有使用 Core Graphics 或任何其他方面的经验,所以这对我来说是一个棘手的问题......
  • 如果有人阅读本文,请查看 iOS7+ 的更新解决方案stackoverflow.com/a/61573384/4260691 OPs 解决方案低于 iOS7。

标签: iphone ios ipad mapkit mkmapview


【解决方案1】:

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

我不知道(文档也没有提到)路径的坐标应该采用什么格式(想到MKMapPointCLLocationCoordinate2D),但您可以通过尝试一下来发现这一点.

【讨论】:

  • 您必须将坐标转换为相对于视图的点,MapView 有一个方法 convetCoordinatestoPoints 和相反,这可能有助于构造 CGPathRef
【解决方案2】:

您已经在评论中回答了自己,但我想向大家指出 GitHub 上出色的 AIMapViewWrapper 项目,其中包括 sample code 用于在一组坐标上绘制弧形路径。在该项目中,它被用来绘制平面所采用的路径,包括其下方的阴影路径(以及其他内容,例如沿该路径为平面设置动画)。应该对任何试图解决这个问题的人派上用场。

【讨论】:

    【解决方案3】:

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

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

    我们现在可以分解一下如何实现圆弧/曲线:

    1. 首先,我们需要定义并添加我们的折线。让我们用 2 个坐标创建一个:
    let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
    mapView.addOverlay(polyline)
    
    1. 添加折线后,MKMapView 将要求我们提供一个正确的MKOverlayRenderer,对应于我们在第 1 节中创建的MKPolyline。我们需要的method 是:

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

    基本上是:

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

    1. 所以让我们提供那个对象。我们希望继承 MKOverlayPathRenderer 的子类,它显然继承自 MKOverlayRenderer,并且如文档所述:

    当您的叠加层的形状由 CGPath 对象定义时,请使用此渲染器。默认情况下,此渲染器填充叠加层的形状并使用其当前属性表示路径的笔触。

    因此,如果我们按原样使用新的子类对象,我们将获得一个开箱即用的解决方案,它是从第 1 坐标到我们在第 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 处更改才能使其正常工作:

    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.boundingBox,而不是使用path.boundingBoxOfPath,因为:

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

    不同于boundingBoxOfPath

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

    希望有帮助:)

    【讨论】:

      【解决方案4】:

      如果你想:

      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. 希望能提供帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-15
        • 1970-01-01
        • 1970-01-01
        • 2014-09-29
        相关资源
        最近更新 更多