我正在 SwiftUI 中构建一个 Apple Watch 应用,它可以读取用户的心率并将其显示在心形符号旁边。
我有一个动画可以让心形符号反复跳动。由于我知道实际用户的心率,因此我希望使其以与用户心率相同的速率跳动,并在每次速率变化时更新动画。
我可以通过将心率除以 60 来确定节拍之间应间隔多少秒。例如,如果用户的心率为 80 BPM,则动画应每 0.75 秒 (60/80) 发生一次。
这是我现在拥有的示例代码,其中currentBPM
是一个常量,但通常会更新。
struct SimpleBeatingView: View {
// Once I get it working, this will come from a @Published Int that gets updated any time a new reading is avaliable.
let currentBPM: Int = 80
@State private var isBeating = false
private let maxScale: CGFloat = 0.8
var beatingAnimation: Animation {
// The length of one beat
let beatLength = 60 / Double(currentBPM)
return Animation
.easeInOut(duration: beatLength)
.repeatForever()
}
var body: some View {
Image(systemName: "heart.fill")
.font(.largeTitle)
.foregroundColor(.red)
.scaleEffect(isBeating ? 1 : maxScale)
.animation(beatingAnimation)
.onAppear {
self.isBeating = true
}
}
}
我希望让这个动画表现得更像苹果的内置心率应用程序。我不想让心脏不断变大或变小,而是想要拥有它beat(两个方向的动画)然后暂停一会儿beating再次(两个方向的动画)然后再次暂停,依此类推。
例如,当我添加一秒延迟时.delay(1)
before .repeatForever()
,动画暂停中途每个节拍。例如,它变小,暂停,然后变大,然后暂停,等等。
我明白为什么会发生这种情况,但是我怎样才能插入延迟between每个自动反转重复而不是在自动反转重复的两端?
我相信我可以算出延迟应该多长时间以及每个节拍的长度的数学计算,以使一切正常工作,因此延迟长度可以是任意的,但我正在寻找的是帮助如何在动画循环之间实现暂停.
我使用的一种方法是flatMap
the currentBPM
重复发表Timer
每次我获得新的心率 BPM 时,我都可以尝试从中驱动动画,但我不确定如何将其实际转换为 SwiftUI 中的动画,并且我不确定以这种方式手动驱动值是否有效根据我目前对 SwiftUI 的理解,当时间似乎应该由动画处理时,正确的方法是。