実現したいこと
北を0度に、現在地のスマホの方向に連動して方向アイコンを回転させたいです。
発生している問題・分からないこと
Image(systemName: "arrow.up") .resizable() .frame(width: 15, height: 15) .foregroundColor(.white) // 矢印を白くする .rotationEffect(.degrees(locationManager.cumulativeAngle)) // ヘディングに基づいてアイコンを回転 Text(String(format: "%.2f", locationManager.cumulativeAngle))
locationManager.cumulativeAngleが0度の時、矢印アイコンは北(0度)をさしていますが、90度のときはなぜか矢印アイコンが180度、180度の時は矢印アイコンは360度をさしています。なぜ矢印アイコンは指定している値(locationManager.cumulativeAngle)の二倍回転するのかわかりません.
どのようにしたらlocationManager.cumulativeAngleの値だけ回転するようになるのかご教示いただきたいです
該当のソースコード
swiftUI
1 2import SwiftUI 3import MapKit 4import CoreLocation 5 6struct ContentView : View { 7 @StateObject private var locationManager = LocationManager() // StateObjectでlocationManagerを管理 8 9 var body: some View { 10 Image(systemName: "arrow.up") 11 .resizable() 12 .frame(width: 15, height: 15) 13 .foregroundColor(.white) // 矢印を白くする 14 .rotationEffect(.degrees(locationManager.cumulativeAngle)) // ヘディングに基づいてアイコンを回転 15 Text(String(format: "%.2f", locationManager.cumulativeAngle)) 16 Text(String(format: "%.2f", locationManager.newHeadingAngle)) 17 } 18} 19 20class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {//class クラス名: スーパークラス, プロトコル 21 let locationManager = CLLocationManager()//NSObjectのクラス 22 var previousHeading: Double = 0.0 // 前回の角度を保持 23 var newHeadingAngle: Double = 0.0 // 前回の角度を保持 24 @Published var cumulativeAngle: Double = 0.0 25 @Published var userLocation: CLLocationCoordinate2D? // ユーザーの現在地 26 27 override init() { 28 super.init()//NSObjectのコンストラクタを実行 29 locationManager.delegate = self 30 locationManager.startUpdatingLocation() // 位置情報の更新を開始 31 locationManager.startUpdatingHeading() // ヘディング(方角)の更新を開始 32 33 } 34 35 // 位置情報が更新されたときに呼ばれる 36 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 37 if let location = locations.last { 38 DispatchQueue.main.async { 39 self.userLocation = location.coordinate // 最新の位置情報を保存 40 } 41 } 42 } 43 44 // 方角(ヘディング)が更新されたときに呼ばれる 45 func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) { 46 newHeadingAngle = newHeading.magneticHeading 47 let shortestAngle = calculateShortestAngle(from: previousHeading, to: newHeadingAngle) 48 DispatchQueue.main.async { 49 print("shortestAngle: \(shortestAngle)") 50 self.cumulativeAngle += shortestAngle // 累積回転角度を更新 51 52 self.cumulativeAngle = self.cumulativeAngle.truncatingRemainder(dividingBy: 360) // 0度~360度に正規化 53 print("cumulativeAngle: \(self.cumulativeAngle)") 54 } 55 previousHeading = newHeadingAngle 56 } 57 58 func requestLocationAuthorization() { 59 locationManager.requestWhenInUseAuthorization() 60 } 61 62 // 2つの角度の間を最短経路で計算するメソッド 63 // 最短回転角度を計算する関数 64 private func calculateShortestAngle(from oldAngle: Double, to newAngle: Double) -> Double { 65 let delta = newAngle - (oldAngle.truncatingRemainder(dividingBy: 360)) 66 if delta > 180 { 67 return delta - 360 // 反時計回りの回転が最短の場合 68 } else if delta < -180 { 69 return delta + 360 // 時計回りの回転が最短の場合 70 } else { 71 return delta // 最短方向で回転 72 } 73 } 74 75} 76 77#Preview { 78 ContentView() 79} 80
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
チャットGPTなどにも聞きましたがあまり要領の得ない回答でした
補足
ios17.5
Xcode15.4
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。