在MKSnapshot图像中绘制带有标题的MKPointAnnotation

Joo*_*ker 2 mkmapview mkannotation mkannotationview swift

我正在尝试绘制一个与"实时"MapView完全相同的注释,但是然后在MKSnapshot中绘制注释.为什么选择MKSnapshot>因为我想在UITableView中使用非交互式MapView并使用图像效率更高.

我可以使用MKPinAnnotationView获取一个引脚(虽然不是iOS 11中的点,引脚看起来很旧),但是图像上没有注释的标题.几乎使用此代码:iOS7中MKMapView的快照.

Ste*_*cht 10

您可以使用以下步骤:

  • 使用MKMapSnapshotter,您将获得没有注释的地图图像

  • 您可以从MKMapView中检索注释

  • 对于每个注释,确定其在图像的坐标空间中的位置

  • 在那里画一个自定义引脚(可能看起来像Apple的引脚)

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

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

在此输入图像描述

这里是上面截图的Swift 4代码:

    @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)
    }
}
Run Code Online (Sandbox Code Playgroud)

替代

如果您更喜欢绘制MKMarkerAnnotationView(例如,为了免费获得漂亮的阴影),您可以将其更改drawPin为:

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)
}
Run Code Online (Sandbox Code Playgroud)

不要忘记将通话更改为

self?.drawPin(point: point, annotation: annotation)
Run Code Online (Sandbox Code Playgroud)

结果如下所示:

在此输入图像描述