簡體   English   中英

如何在 UIView 中繪制與 MKPolyline 相同的 UIBezierPath

[英]How to draw UIBezierPath identical to MKPolyline in a UIView

目前我正在 MKMapView 上跟蹤我的位置。 我的目標是繪制一條與從跟蹤位置創建的 MKPolyline 相同的貝塞爾曲線路徑。

我嘗試的是:將所有位置坐標存儲在 CLLocation 數組中。 迭代該數組並將緯度/經度坐標存儲在 CLLocationCoordinate2D 數組中。 然后確保折線在屏幕視圖中,然后轉換 CGPoints 中的所有位置坐標。

當前嘗試:

@IBOutlet weak var bezierPathView: UIView! 

var locations = [CLLocation]() // values from didUpdateLocation(_:)

func createBezierPath() {
    bezierPathView.isHidden = false

        var coordinates = [CLLocationCoordinate2D]()
        for location in locations {
            coordinates.append(location.coordinate)
        }

        let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
        fitPolylineInView(polyline: polyline)

        let mapPoints = polyline.points()

        var points = [CGPoint]()

        for point in 0...polyline.pointCount
        {
            let coordinate = MKCoordinateForMapPoint(mapPoints[point])
            points.append(mapView.convert(coordinate, toPointTo: polylineView))
        }

        print(points)

        let path = UIBezierPath(points: points)
        path.lineWidth = 2.0
        path.lineJoinStyle = .round

        let layer = CAShapeLayer(path: path, lineColor: UIColor.red, fillColor: UIColor.black)
        bezierPathView.layer.addSublayer(layer)
}

extension UIBezierPath {
    convenience init(points:[CGPoint])
    {
        self.init()

        //connect every points by line.
        //the first point is start point
        for (index,aPoint) in points.enumerated()
        {
            if index == 0 {
                self.move(to: aPoint)
            }
            else {
                self.addLine(to: aPoint)
            }
        }
    }
}

extension CAShapeLayer
{
    convenience init(path:UIBezierPath, lineColor:UIColor, fillColor:UIColor)
    {
        self.init()
        self.path = path.cgPath
        self.strokeColor = lineColor.cgColor
        self.fillColor = fillColor.cgColor
        self.lineWidth = path.lineWidth

        self.opacity = 1
        self.frame = path.bounds
    }
}

我能夠將點輸出到從 convert(_:) 方法存儲的控制台(不確定它們是否正確)。 然而 bezierPathView 上沒有輸出 - 導致空白色背景視圖控制器。

您的擴展工作正常。 問題可能出在將圖層添加到視圖(您沒有顯示)的代碼中。

我建議您簡化您的項目,例如使用絕對適合您的觀點的預定義點數組。 例如,對於 500 像素寬和 300 像素高的視圖,您可以使用以下內容:

let points = [
    CGPoint(x: 10, y: 10),
    CGPoint(x: 490, y: 10),
    CGPoint(x: 490, y: 290),
    CGPoint(x: 10, y: 290),
    CGPoint(x: 10, y: 10)
]

使用清晰可見的顏色,例如黑色和黃色用於筆觸和填充。

確保您的路徑正確添加到視圖中,例如:

let path = UIBezierPath(points: points)

let shapeLayer = CAShapeLayer(path: path, lineColor: UIColor.blue, fillColor: UIColor.lightGray)

view.layer.addSublayer(shapeLayer)

在 Xcode 的 Interface Builder 中檢查包含視圖的控​​制器。 在調試視圖層次功能中:

在此處輸入圖片說明

如果您還沒有解決它,這可能會對您有所幫助。

我想要 MKPolyline 的形狀作為沒有任何背景的圖像。 我用上面的代碼作為靈感,遇到了和你一樣的麻煩,沒有顯示路線。

事實上,我認為這是一個縮放問題。 至少在操場上是這樣的。 無論如何,通過這種方法,我得到了折線形狀的圖像。

private func createPolylineShapeAsImage() -> UIImage? {
    let vw = UIView(frame: mapView.bounds)
    var image : UIImage?
    if let polyline = viewModel.tourPolyline {
        let path = createBezierPath(mapView, polyline, to: mapView)
        let layer = getShapeLayer(path: path, lineColor: UIColor.white, fillColor: .clear)
        vw.layer.addSublayer(layer)
        image = vw.asImage()
    }
    return image
}

func createBezierPath(_ mapView : MKMapView, _ polyline : MKPolyline, to view : UIView) -> UIBezierPath  {
    let mapPoints = polyline.points()
    var points = [CGPoint]()
    let max = polyline.pointCount - 1
    for point in 0...max {
       let coordinate = mapPoints[point].coordinate
       points.append(mapView.convert(coordinate, toPointTo: view))
    }
    let path = UIBezierPath(points: points)
    path.lineWidth = 5.0
    return path
}

private func getShapeLayer(path:UIBezierPath, lineColor:UIColor, fillColor:UIColor) -> CAShapeLayer {
    let layer = CAShapeLayer()
    layer.path = path.cgPath
    layer.strokeColor = lineColor.cgColor
    layer.fillColor = fillColor.cgColor
    layer.lineWidth = path.lineWidth

    layer.opacity = 1
    layer.frame = path.bounds
    return layer
}

並使用此擴展程序獲取視圖的圖像

import UIKit
extension UIView {
  // Using a function since `var image` might conflict with an existing variable
  // (like on `UIImageView`)
  func asImage() -> UIImage {
    if #available(iOS 10.0, *) {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    } else {
        UIGraphicsBeginImageContext(self.frame.size)
        self.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return UIImage(cgImage: image!.cgImage!)
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM