SwiftUI 动画旋转故障@ 360/0 度标记

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

所以我有一个根据设备指向的方向设置的特定度数旋转的视图。问题是当你从 359.99 度旋转到 0.01 度旋转时(这是实际中最小的差异,视图选择从 360 度向下一直旋转到 0 度,而不是仅仅环绕。这会导致动画出现问题,因为它使视图旋转 359 度回到 0 位置,而不是仅仅从 359 度单击到 0 度位置。我已经尝试将 359-360 和 0-1 之间的动画设置为 nil,但是如果您移动设备的速度足够快,您仍然会看到这个糟糕的动画。有什么建议吗?

Image("arrow")
    .rotationEffect(Angle(degrees: deviceHeading))
    .animation(.easeOut)

https://youtu.be/MzpI6THHS8U

正如您所看到的,就在该位置,它会完全旋转,而不仅仅是采取短路径到达新位置。

swift animation swiftui transition
1个回答
0
投票

自 iOS 17 / watchOS 10 / tvOS 17 / macOS 14 / Mac Catalyst 17 / VisionOS 1 开始

在 SwiftUI 中

withAnimation
现在有一个completionHandler。 https://developer.apple.com/documentation/swiftui/withanimation(_:完成标准:_:完成:)

所以你可以根据动画的最短路径临时计算新的旋转度数。然后,一旦动画完成,您就可以将旋转度数校正为设备航向的实际值。

这是我认为应该有效的代码片段(尚未测试):

@available(watchOS 10.0, *)
struct CompassArrowView: View {
    var deviceHeading: CLLocationDegrees
    @State private var rotationDegrees: CLLocationDegrees = .zero

    init(deviceHeading: CLLocationDegrees) {
        self.deviceHeading = deviceHeading
        self.rotationDegrees = deviceHeading
    }

    var body: some View {
        Image("arrow")
            .rotationEffect(.degrees(rotationDegrees))
            .onChange(of: deviceHeading) { oldValue, newValue in
                if abs(newValue - oldValue) > 180.0 {
                    if newValue < oldValue {
                        withAnimation(.easeOut) { [self] in
                            rotationDegrees = newValue
                        } completion: { [self] in
                            rotationDegrees = rotationDegrees - 360
                        }
                    } else {
                        rotationDegrees = oldValue + 360
                        withAnimation(.easeOut) { [self] in
                            rotationDegrees = newValue
                        }
                    }
                } else {
                    withAnimation(.easeOut) { [self] in
                        rotationDegrees = newValue
                    }
                }
            }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.