如何根据位置变化在 MapKit 中为 iOS 17 中的新注释设置动画?

问题描述 投票:0回答:1

在 MK 中这是很困难的,但我似乎找不到任何可以与新 MapKit 配合使用的东西。

需求:当位置发生变化时,将注释从

oldValue
平滑动画到
newValue

所以我几乎尝试了所有方法,但最终想到了将

oldValue
newValue
之间的增量细分为 100,然后强力更新每个分数的位置的想法。这是我正在使用的功能:

func animateAnnotationMove(from oldCoordinate: CLLocationCoordinate2D, to newCoordinate: CLLocationCoordinate2D, steps: Int = 100, interval: TimeInterval = 0.05) {
    let latitudeDiff = (newCoordinate.latitude - oldCoordinate.latitude) / Double(steps)
    let longitudeDiff = (newCoordinate.longitude - oldCoordinate.longitude) / Double(steps)
    
    var currentStep = 0
    Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] timer in
        guard currentStep < steps else {
            timer.invalidate() // Stop the timer
            return
        }
        
        let nextLatitude = oldCoordinate.latitude + (latitudeDiff * Double(currentStep))
        let nextLongitude = oldCoordinate.longitude + (longitudeDiff * Double(currentStep))
        let nextCoordinate = CLLocaionCoordinate2D(latitude: nextLatitude, longitude: nextLongitude)
        
        DispatchQueue.main.async {
            self?.updateGuestAnnotationPosition(with: nextCoordinate)
        }
        
        currentStep += 1
    }
}

我担心的是,随着我的扩展,这并不是很有效,并且由于 SwiftUI 能够在许多其他领域进行动画处理,也许我错过了一些明显的东西?我的位置数据每 5 秒更新一次,因此这里的想法是将其分解为 100 个函数调用(因此每 0.05 秒一次)并为增量设置动画。

ios swiftui mapkit ios17
1个回答
0
投票

这就是我如何将自定义注释设置为动画,包括将注释保持在中心的地图。

@State private var cameraPosition: MapCameraPosition = .region(MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0, longitude: 0), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)))

var body: some View {
        
        @State var location: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: plane.lat ?? 0, longitude: plane.lon ?? 0)
        
        @State var region: MKCoordinateRegion = MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta: 0.3, longitudeDelta: 0.3))
        
        Map(
            position: $cameraPosition,
            //initialPosition: .region(region)
            interactionModes: [.pan, .zoom]
        ) {
            
            Annotation(coordinate: location) {
                
                Image(systemName: "airplane")
                    .rotationEffect(Angle(degrees: (plane.track ?? 0) + -90))
                    .animation(.easeInOut(duration: 1.5), value: plane.track)
                
            } label: {
                Label {
                    VStack(alignment: .leading) {
                        Text(plane.desc ?? "")
                    }
                } icon: {
                    Image(systemName: "airplane")
                }
            }
        }
        .onChange(of: plane.lon) {
            withAnimation(.smooth(duration:  3.5)) {
                location = CLLocationCoordinate2D(latitude: plane.lat ??  0, longitude: plane.lon ??  0)
                region = MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta:  0.3, longitudeDelta:  0.3))
                cameraPosition = .region(region)
            }
        }
        .animation(.easeInOut(duration: 0.5), value: location)
        .mapControlVisibility(.visible)
        .ignoresSafeArea()
    }
© www.soinside.com 2019 - 2024. All rights reserved.