xyk blog

最近は iOS 開発の記事が多めです。

MKMapView 上のタップした地点を中心にして円を描く

検証環境:
Xcode 12
Swift 5.3

f:id:xyk:20201110172554j:plain

地図上(MKMapView)に図形を描画するためにはMKOverlayプロトコルに適合したオブジェクトをMKMapView#addOverlayメソッドで追加する必要がある。

まずMapKitをインポートしておく。

import MapKit
  • MKMapView にUITapGestureRecognizerを追加してタップを検出する。
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(mapTapped(_:)))
mapView.addGestureRecognizer(tapGesture)
  • この時呼び出すmapTappedメソッドを定義する。
    ここではタップ位置を中心としたMKCircleオブジェクトを作成してMKMapView#addOverlayで追加する。
@objc func mapTapped(_ sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        let tapPoint = sender.location(in: mapView)
        // タップした座標(CGPoint)を緯度経度(CLLocationCoordinate2D)に変換する
        let center = mapView.convert(tapPoint, toCoordinateFrom: view)
        // 半径100m を指定
        let circle = MKCircle(center: center, radius: CLLocationDistance(100))
        mapView.addOverlay(circle)
    }
}
  • MKMapViewDelegateデリゲートを使う準備
mapView.delegate = self
  • デリゲートメソッドmapView(_:rendererFor:)を実装して、MKCircleRendererオブジェクトを生成する。
    このデリゲートメソッドはMKMapView#addOverlayで追加された時に呼ばれる。
extension ViewController: MKMapViewDelegate {

    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        
        if let circle = overlay as? MKCircle {
            let renderer = MKCircleRenderer(circle: circle)
            renderer.strokeColor = UIColor.red // 枠線の色
            renderer.fillColor = UIColor.red.withAlphaComponent(0.2) // 内側の色
            renderer.lineWidth = 2 // 枠線の太さ
            return renderer
        }
        
        return MKOverlayRenderer()
    }
}