在MKSnapshot图像中用标题绘制MKPointAnnotation [英] Draw MKPointAnnotation with title in MKSnapshot image

查看:103
本文介绍了在MKSnapshot图像中用标题绘制MKPointAnnotation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图绘制一个与实时" MapView中完全相同的注释,但随后在MKSnapshot中绘制一个注释.为什么要使用MKSnapshot>,因为我想在UITableView中使用非交互式MapView并使用图像更有效.

I'm trying to draw an annotation exactly as in a 'live' MapView, but then in a MKSnapshot. Why an MKSnapshot > because I want to have non-interactive MapViews in a UITableView and using images is more efficient.

我可以使用MKPinAnnotationView绘制图钉(尽管不是iOS 11中的点,该图钉看起来很旧),但是图像上没有注释的标题.几乎完全使用以下代码: iOS7中的MKMapView快照.

I can get a pin to be drawn (though not a point as in iOS 11, the pin looks old) using MKPinAnnotationView, but also then there is no title of the annotation on the image. Using almost exactly this code: Snapshot of MKMapView in iOS7.

推荐答案

您可以使用以下步骤:

  • 使用MKMapSnapshotter,您将获得不带注释的地图图像

  • with MKMapSnapshotter you will get an image of the map without annotations

您可以从MKMapView中检索注释

you can retrieve the annotations from your MKMapView

为每个注释确定其在图像坐标空间中的位置

for each annotations determine its position in the coordinate space of the image

在此处绘制自定义图钉(可能看起来像苹果的图钉)

draw a custom pin there (may look like Apple's pins)

确定注释标题的文本和大小并将其绘制在图钉位置下方的中心

determine the text and size of the annotation title and draw it centered below the position of the pin

结果看起来与MKMapView显示的结果非常相似.在所附的屏幕截图中,上部区域有一个MKMapView,下部区域有一个UIImageView及其结果图像.看起来很相似,不是吗?

The result can look very similar to what MKMapView displays. In the attached screenshot there is a MKMapView in the upper area and an UIImageView with the resulting image in the lower area. Looks similar, doesn't it?

以下是上述屏幕快照的Swift 4代码:

Here the Swift 4 code for the screenshot above:

    @IBOutlet weak var imageView: UIImageView!

    @IBAction func onSnap(_ sender: Any) {
        let options: MKMapSnapshotOptions = MKMapSnapshotOptions()
        options.region = self.mapView.region
        options.size = self.mapView.frame.size
        options.scale = UIScreen.main.scale

        let customPin = UIImage(named: "customPin.pdf")

        let snapshotter = MKMapSnapshotter(options: options)
        snapshotter.start { [weak self] (snapshot: MKMapSnapshot?, error: Error?) -> Void in
            guard error == nil, let snapshot = snapshot else { return }

            UIGraphicsBeginImageContextWithOptions(snapshot.image.size, true, snapshot.image.scale)
            snapshot.image.draw(at: CGPoint.zero)

            let titleAttributes = self?.titleAttributes()
            for annotation in (self?.mapView.annotations)! {
                let point: CGPoint = snapshot.point(for: annotation.coordinate)
                if let customPin = customPin {
                    self?.drawPin(point: point, customPin: customPin)
                }
                if let title = annotation.title as? String {
                    self?.drawTitle(title: title,
                                    at: point,
                                    attributes: titleAttributes!)
                }
            }
            let compositeImage = UIGraphicsGetImageFromCurrentImageContext()
            self?.imageView.image = compositeImage
        }
    }

    private func drawTitle(title: String,
                           at point: CGPoint,
                           attributes: [NSAttributedStringKey: NSObject]) {
        let titleSize = title.size(withAttributes: attributes)
        title.draw(with: CGRect(
            x: point.x - titleSize.width / 2.0,
            y: point.y + 1,
            width: titleSize.width,
            height: titleSize.height),
                   options: .usesLineFragmentOrigin,
                   attributes: attributes,
                   context: nil)
    }

    private func titleAttributes() -> [NSAttributedStringKey: NSObject] {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = .center
        let titleFont = UIFont.systemFont(ofSize: 10, weight: UIFont.Weight.semibold)
        let attrs = [NSAttributedStringKey.font: titleFont,
                     NSAttributedStringKey.paragraphStyle: paragraphStyle]
        return attrs
    }

    private func drawPin(point: CGPoint, customPin: UIImage) {
        let pinPoint = CGPoint(
            x: point.x - customPin.size.width / 2.0,
            y: point.y - customPin.size.height)
        customPin.draw(at: pinPoint)
    }
}

替代

如果您希望绘制MKMarkerAnnotationView(例如免费获得漂亮的阴影),则可以将drawPin更改为此:

If you prefer to draw a MKMarkerAnnotationView (e.g. to get the nice shadow for free) you can change the drawPin to this:

private func drawPin(point: CGPoint, annotation: MKAnnotation) {
    let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "test")
    annotationView.contentMode = .scaleAspectFit
    annotationView.bounds = CGRect(x: 0, y: 0, width: 40, height: 40)
    annotationView.drawHierarchy(in: CGRect(
        x: point.x - annotationView.bounds.size.width / 2.0,
        y: point.y - annotationView.bounds.size.height,
        width: annotationView.bounds.width,
        height: annotationView.bounds.height),
                                 afterScreenUpdates: true)
}

别忘了将通话更改为

self?.drawPin(point: point, annotation: annotation)

结果如下:

这篇关于在MKSnapshot图像中用标题绘制MKPointAnnotation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆