目標
MKMarkerAnnotationViewのようなテキスト付きのアノテーションを好きなSFSymbolsでつくる
個人開発のアプリでお恥ずかしいが「城北町」のピンを作りたかった。「休憩」はデフォルトのMKMakerAnnotationView
方法
既存の部分の色を無理やり.clear
にしてゴリ押した。
色が変わらなかったのでUIImageView
を一度経由して色を変えてレンダリングしたものを使う。
final class IconAnnotation: MKPointAnnotation {
let icon: String
init(title: String, icon: String) {
self.icon = icon
super.init()
self.title = title
}
}
final class IconAnnotationView: MKMarkerAnnotationView {
static let identifier = "IconAnnotationView"
override var annotation: MKAnnotation? {
willSet {
guard let iconAnnotation = newValue else { return }
guard let baseImage = UIImage(systemName: iconAnnotation.icon) else { return }
// サイズがそのままでは小さかったのでお好みで調整
let scale: CGFloat = 1.5
let newSize = CGSize(width: baseImage.size.width * scale,
height: baseImage.size.height * scale)
let imageView = UIImageView(image: baseImage)
imageView.bounds = CGRect(origin: .zero, size: newSize)
// 任意のカラー
imageView.backgroundColor = .clear
imageView.tintColor = .red
// レンダリング
let renderer = UIGraphicsImageRenderer(size: newSize)
let renderedImage = renderer.image { _ in
imageView.drawHierarchy(in: CGRect(origin: .zero, size: newSize), afterScreenUpdates: true)
}
image = renderedImage
displayPriority = .required
//既存のデザインを無効化
markerTintColor = .clear
glyphTintColor = .clear
glyphImage = nil
}
}
}
extension IconAnnotationView {
static func view(for mapView: MKMapView, annotation: FloatAnnotation) -> MKAnnotationView {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? FloatAnnotationView
if annotationView == nil {
annotationView = IconAnnotationView(annotation: annotation, reuseIdentifier: identifier)
} else {
annotationView?.annotation = annotation
}
return annotationView!
}
}
//MKMapViewDelegate
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if let iconAnnotation = annotation as? IconAnnotation {
return IconAnnotationView.view(for: mapView, annotation: iconAnnotation)
}
return nil
}