如何在 swift 3 中将 MKPolylines 添加到 MKSnapShotter?

Posted

技术标签:

【中文标题】如何在 swift 3 中将 MKPolylines 添加到 MKSnapShotter?【英文标题】:How do you add MKPolylines to MKSnapShotter in swift 3? 【发布时间】:2016-07-18 22:18:57 【问题描述】:

有没有办法截取 mapView 并包含折线?我相信我需要在 MKSnapShotter 返回的图像上绘制 CGPoint,但我不确定如何这样做。

当前代码

      func takeSnapshot(mapView: MKMapView, withCallback: (UIImage?, NSError?) -> ()) 
    let options = MKMapSnapshotOptions()
    options.region = mapView.region
    options.size = mapView.frame.size
    options.scale = UIScreen.main().scale

    let snapshotter = MKMapSnapshotter(options: options)


    snapshotter.start()  snapshot, error in
        guard snapshot != nil else 
            withCallback(nil, error)
            return
        

        if let image = snapshot?.image



            withCallback(image, nil)

            for coordinate in self.area 

                image.draw(at:snapshot!.point(for: coordinate))

            

        

    

【问题讨论】:

在Putting Map Kit in Perspective 视频中,Apple 演示了如果您想在快照中包含注释,您必须自己手动绘制它们。 (令人困惑,是的,但事实就是如此。)我认为 MKPolyline 之类的叠加层也是如此。 谢谢,我去看看。 好的,视频内容丰富,但并没有真正的帮助。 我原以为演示,在快照中手动渲染注释图钉,会给你足够的线索如何用覆盖做等效的...... 【参考方案1】:

我今天也遇到了同样的问题。经过几个小时的研究,这是我的解决方法。

以下代码在 Swift 3 中。

1。初始化你的折线坐标数组

// initial this array with your polyline coordinates
var yourCoordinates = [CLLocationCoordinate2D]() 
yourCoorinates.append( coordinate 1 )
yourCoorinates.append( coordinate 2 )
...
// you can use any data structure you like

2。照常拍摄快照,但根据您的坐标设置区域:

func takeSnapShot() 
    let mapSnapshotOptions = MKMapSnapshotOptions()

    // Set the region of the map that is rendered. (by polyline)
    let polyLine = MKPolyline(coordinates: &yourCoordinates, count: yourCoordinates.count)
    let region = MKCoordinateRegionForMapRect(polyLine.boundingMapRect)

    mapSnapshotOptions.region = region

    // Set the scale of the image. We'll just use the scale of the current device, which is 2x scale on Retina screens.
    mapSnapshotOptions.scale = UIScreen.main.scale

    // Set the size of the image output.
    mapSnapshotOptions.size = CGSize(width: IMAGE_VIEW_WIDTH, height: IMAGE_VIEW_HEIGHT)

    // Show buildings and Points of Interest on the snapshot
    mapSnapshotOptions.showsBuildings = true
    mapSnapshotOptions.showsPointsOfInterest = true

    let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)

    snapShotter.start()  snapshot, error in
        guard let snapshot = snapshot else 
            return
        
        // Don't just pass snapshot.image, pass snapshot itself!
        self.imageView.image = self.drawLineOnImage(snapshot: snapshot)
    

3。使用 snapshot.point() 在 Snapshot Image 上绘制折线

func drawLineOnImage(snapshot: MKMapSnapshot) -> UIImage 
    let image = snapshot.image

    // for Retina screen
    UIGraphicsBeginImageContextWithOptions(self.imageView.frame.size, true, 0)

    // draw original image into the context
    image.draw(at: CGPoint.zero)

    // get the context for CoreGraphics
    let context = UIGraphicsGetCurrentContext()

    // set stroking width and color of the context
    context!.setLineWidth(2.0)
    context!.setStrokeColor(UIColor.orange.cgColor)

    // Here is the trick :
    // We use addLine() and move() to draw the line, this should be easy to understand.
    // The diificult part is that they both take CGPoint as parameters, and it would be way too complex for us to calculate by ourselves
    // Thus we use snapshot.point() to save the pain.
    context!.move(to: snapshot.point(for: yourCoordinates[0]))
    for i in 0...yourCoordinates.count-1 
      context!.addLine(to: snapshot.point(for: yourCoordinates[i]))
      context!.move(to: snapshot.point(for: yourCoordinates[i]))
    

    // apply the stroke to the context
    context!.strokePath()

    // get the image from the graphics context
    let resultImage = UIGraphicsGetImageFromCurrentImageContext()

    // end the graphics context 
    UIGraphicsEndImageContext()

    return resultImage!

就是这样,希望这对某人有帮助。

参考文献

How do I draw on an image in Swift?

MKTile​Overlay,MKMap​Snapshotter & MKDirections

Creating an MKMapSnapshotter with an MKPolylineRenderer

Render a Map as an Image using MapKit

【讨论】:

@user287589 如何计算区域跨度以在快照上插入? @AymenHARRATH 我不知道。对不起 我尝试运行这个 sn-p 代码。它在这一行中给了我以下错误: context!.setLineWidth(2.0) 错误消息说:“致命错误:在展开可选值时意外发现 nil”【参考方案2】:

有什么问题:

snapshotter.start( completionHandler:  snapshot, error in
  guard snapshot != nil else 
    withCallback(nil, error)
    return
  

  if let image = snapshot?.image 
    withCallback(image, nil)

    for coordinate in self.area 
      image.draw(at:snapshot!.point(for: coordinate))
    

  
)

【讨论】:

我最终只是将坐标存储在一个数组中,然后将它们显示在我在另一个视图中创建的地图上。【参考方案3】:

如果您只想要用户在 MKMapView 中看到的图像的副本,请记住它是 UIView 子类,因此您可以这样做...

public extension UIView 
    public var snapshot: UIImage? 
        get 
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
            self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        
    


// ...
if let img = self.mapView.snapshot 
    // Do something

【讨论】:

以上是关于如何在 swift 3 中将 MKPolylines 添加到 MKSnapShotter?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Alamofire,swift 3 中将字典作为参数发送

如何在 Swift 3 中将 NSConstraints 添加到 UITextView

如何在 swift 3 中将 MKPolylines 添加到 MKSnapShotter?

如何在 swift 3 中将滑动手势添加到 AVPlayer

iOS 3 中 MKPolyline 的等价物

如何在 Swift 3 中将字典表示为 NSValue?