SwiftUI не только дает нам автоматическую c анимацию ... он позволяет нам контролировать процесс анимации, используя свойство animatableData
. Так круто!
Только я не могу заставить его работать. Следующий код отображает циферблат на экране (цифры 0… 11 ?) и показывает тумблер. Переключение тумблера поворачивает цифры на 180 градусов, анимированные. Или это мое намерение. Но вместо того, чтобы каждое число проходило анимированный путь вокруг круга чисел, каждое число перемещалось по прямой линии в свою новую позицию… так, чтобы круг чисел сворачивался в центральную точку круга и затем снова взрывался в его новую конфигурацию:
На свойство animatableData
не ссылается SwiftUI. Любая идея, почему?
(Обратите внимание, что не будет работать стандартная анимация вращения, потому что это перевернет все числа вверх ногами.)
import SwiftUI
struct ContentView: View {
@State var state: Bool = false
var body: some View {
VStack {
CircleView(hoursOffset: CGFloat(state ? 6 : 0 ))
.aspectRatio(contentMode: .fit)
Toggle(isOn: $state, label: { Text("Rotate 180°?") })
.frame(maxWidth: 200).padding()
}
}
}
extension CGPoint {
static func onCircle(hours: CGFloat, size: CGFloat) -> CGPoint {
let radians = (3 - hours) * CGFloat.pi / CGFloat (6)
let hypotenuse = size / 2
return CGPoint(x: size / 2 + 0.8 * hypotenuse * cos(radians),
y: size / 2 - 0.8 * hypotenuse * sin(radians))
}
}
struct CircleView: View {
var hoursOffset: CGFloat
public var animatableData: CGFloat {
get { hoursOffset }
set { self.hoursOffset = newValue }
}
var body: some View {
GeometryReader() { geo in
ForEach(0..<12) { hour in
ZStack {
Text("\(hour)")
.position(CGPoint.onCircle(hours: CGFloat(hour) + self.hoursOffset, size: geo.size.width))
.animation(Animation.easeInOut(duration: 2.0))
}
}
}
}
}