【发布时间】:2020-12-30 15:57:51
【问题描述】:
我正在使用 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
}
}
}
我想让这个动画表现得更像 Apple 的内置心率应用程序。与其让心脏不断变大或变小,我想让它跳动(两个方向的动画)然后暂停片刻,然后再次跳动(动画两个方向)然后再次暂停,依此类推。
当我添加一秒延迟时,例如,.delay(1) 在.repeatForever() 之前,动画会在每个节拍中途暂停。例如,它变小,暂停,然后变大,然后暂停,等等。
我明白为什么会发生这种情况,但是如何在每个自动反转重复之间插入延迟,而不是在自动反转重复的两端插入?
我相信我可以计算出延迟应该多长以及每个节拍的长度以使一切正常进行,因此延迟长度可以是任意的,但我正在寻找的是帮助关于如何在动画循环之间实现暂停。
我使用的一种方法是在每次获得新的心率 BPM 时将flatMap 和currentBPM 重复发布的Timers,这样我就可以尝试从中驱动动画,但我不确定如何实际上,我可以将其转换为 SwiftUI 中的动画,但根据我目前对 SwiftUI 的理解,当时间似乎应该由动画处理时,我不确定以这种方式手动驱动值是否是正确的方法。
【问题讨论】: