在 UIImage 中渲染 MKPolyline

Render a MKPolyline in a UIImage

我需要在不使用 MKMapView 的情况下在 UIImage 中渲染 MKPolyline (主要是出于性能原因,我想尽快显示路径,而地图截屏器异步提供地图,就像应用程序 Strava 所做的那样)。

我想出了这段代码:

func pathImageForSize(size: CGSize) -> UIImage {
    let region = regionForPath() // MKCoordinateRegion
    let coordinates = locations.map { [=10=].coordinate }
    UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)

    let context = UIGraphicsGetCurrentContext()

    CGContextSetStrokeColorWithColor(context, UIColor.palette_mainColor().CGColor)
    CGContextSetLineWidth(context, 4.0)
    CGContextBeginPath(context)

    let origin = CGPoint(x: region.center.latitude - region.span.latitudeDelta / 2, y: region.center.longitude - region.span.longitudeDelta / 2)

    for (index, coordinate) in coordinates.enumerate() {
        let point = CGPoint(x: ((CGFloat(coordinate.latitude) - origin.x) / CGFloat(region.span.latitudeDelta)) * size.width,
                            y: ((CGFloat(coordinate.longitude) - origin.y) / CGFloat(region.span.longitudeDelta)) * size.height)

        if index == 0 {
            CGContextMoveToPoint(context, point.x, point.y)
        } else {
            CGContextAddLineToPoint(context, point.x, point.y)
        }
    }

    CGContextStrokePath(context)

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

代码基本上重新缩放坐标并使用 CoreGraphics 绘制它们。 路径已绘制,但也旋转了 90 度,如下所示:

MapKit 渲染的多段线:

我的代码呈现的多段线:

知道我做错了什么吗?

我怀疑这是因为您将纬度用作 'x',将经度用作 'y'。纬度是垂直维度(在顶部为北的地图上),经度是水平维度。

好的,明白了,我的前提是错误的: 我正在计算的区域封装了路径的坐标,但该区域在渲染时由 mapview 进行了调整。解决方案是缩放区域以适合地图视图的框架:

let map = MKMapView(frame: CGRect(origin: CGPoint.zero, size: size))
let region = map.regionThatFits(regionForPath())

此外,正如 BrentM 所建议的那样,坐标被翻转了。结果代码是这样的:

func pathImageForSize(size: CGSize) -> UIImage {
  let map = MKMapView(frame: CGRect(origin: CGPoint.zero, size: size))
  let region = map.regionThatFits(regionForPath())
  let coordinates = locations.map { [=11=].coordinate }
  UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)

  let context = UIGraphicsGetCurrentContext()
  CGContextSetLineJoin(context, .Round)
  CGContextSetLineCap(context, .Round)
  CGContextSetStrokeColorWithColor(context, UIColor.palette_mainColor().CGColor)
  CGContextSetLineWidth(context, 4.0)
  CGContextBeginPath(context)

  let origin = CGPoint(x: region.center.longitude - region.span.longitudeDelta / 2, y: region.center.latitude - region.span.latitudeDelta / 2)

  for (index, coordinate) in coordinates.enumerate() {
    let point = CGPoint(x: ((CGFloat(coordinate.longitude) - origin.x) / CGFloat(region.span.longitudeDelta)) * size.width,
                        y: ((CGFloat(coordinate.latitude) - origin.y) / CGFloat(region.span.latitudeDelta)) * size.height)

    if index == 0 {
      CGContextMoveToPoint(context, point.x, size.height - point.y)
    } else {
      CGContextAddLineToPoint(context, point.x, size.height - point.y)
    }
  }

  CGContextStrokePath(context)

  let image = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return image
}