簡體   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