所以我有一个根据设备指向的方向设置的特定度数旋转的视图。问题是当你从 359.99 度旋转到 0.01 度旋转时(这是实际中最小的差异,视图选择从 360 度向下一直旋转到 0 度,而不是仅仅环绕。这会导致动画出现问题,因为它使视图旋转 359 度回到 0 位置,而不是仅仅从 359 度单击到 0 度位置。我已经尝试将 359-360 和 0-1 之间的动画设置为 nil,但是如果您移动设备的速度足够快,您仍然会看到这个糟糕的动画。有什么建议吗?
Image("arrow")
.rotationEffect(Angle(degrees: deviceHeading))
.animation(.easeOut)
正如您所看到的,就在该位置,它会完全旋转,而不仅仅是采取短路径到达新位置。
自 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
}
}
}
}
}