🐾

MKMapViewでユーザーの方角を表示し、カメラの自動回転を無効にする

2023/04/30に公開

はじめに

MKMapViewでユーザーの方角を表示するには、userTrackingModefollowWithHeadingにすれば良いです。

mapView.userTrackingMode = .followWithHeading

これでユーザーの方向を表示できるのですが、カメラが自動で回転するようになります。
ユーザーの方角表示を自前実装することで、要件を満たすことができたので、方法を共有しようと思います。

実装方針

  1. ユーザーの現在地を表示する
  2. 現在地を表すAnnotationの画像を別画像に変更
  3. ユーザーの方角を取得し、画像を回転させる

1. ユーザーの現在地を表示する

mapView.showsUserLocation = true

2. 現在地を表すAnnotationの画像を別画像に変更

MKMapViewのデリゲートメソッドで、ユーザーの現在地を表すAnnottionの画像を書き換える。
そして、クラス直下でそのAnnotationを保持しておく。

private var userLocationAnnotationView: MKAnnotationView?

func mapView(
    _ mapView: MKMapView,
    viewFor annotation: MKAnnotation
) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        var userLocationAnnotation = mapView.dequeueReusableAnnotationView(withIdentifier: "userLocation")
        if userLocationAnnotation == nil {
            userLocationAnnotation = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
        }
        
        let image = UIImage(systemName: "location.north.circle")
        userLocationAnnotation?.image = image
        userLocationAnnotation?.annotation = annotation
        userLocationAnnotation?.frame = .init(x: 0, y: 0, width: 30, height: 30)
        
        self.userLocationAnnotationView = userLocationAnnotation

        return userLocationAnnotation
    }
    
    return nil
}

3. ユーザーの方角を取得し、画像を回転させる

CLLocationManagerのデリゲートメソッドで、ユーザーの方向を取得。

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
    // クラス直下に格納しておいた現在地を表すAnnotation
    guard let userLocationAnnotationView = userLocationAnnotationView else { return }

    // ラジアンに変換し、画像を回転
    let angle = CGFloat(newHeading.trueHeading) * .pi / 180
    let transform = CGAffineTransform(rotationAngle: angle)
    userLocationAnnotationView.transform = transform
}

最後に

ポイントだけ説明しました。

全体が確認したい方はこちら↓↓
https://github.com/HikaruKurodq/MKMapViewUserLocation

GitHubで編集を提案
カラビナテクノロジー デベロッパーブログ

Discussion