我正在探索 SwiftUI View
中的正弦波渲染,并已将我的 View 构建为具有 3 个可控参数:
phase
(控制偏移并允许“水平”动画)amplitude
(控制每个峰值的高度)频率
(有多少个完整的波)
截图如下:
我的 SineWave
是作为 Shape
实现的,因此它已经是 Animatable
了。我制作了 amplitude
和 frequency
一个 AnimatablePair
并将其公开为我的形状的 animatable
数据,如下所示:
var animatableData: AnimatablePair<CGFloat, CGFloat> {
get { .init(frequency, amplitude) }
set {
frequency = newValue.first
amplitude = newValue.second
}
}
这行得通,如果我在包含 View 中这样做,我会得到一个漂亮的动画:
SineWaveShape(phase: phase, amplitude: amplitude, frequency: frequency)
.stroke(style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
.foregroundColor(.red)
.onAppear {
withAnimation(Animation.spring(response: 0.5, dampingFraction: 0.4, blendDuration: 0.1).repeatForever()) {
amplitude = 0.1
frequency = 4
}
}
现在我也想为 phase
设置动画。但我不希望这个自动反转,我希望它快得多。不幸的是,在这个 block 旁边添加另一个 withAnimation
block 没有任何效果,即使我将它作为我的动画数据的一部分。最后一个动画 block 总是获胜。
我应该如何解决想要使用两个不同的 Animation
实例为两个属性设置动画的问题?
最佳答案
这是可能的方法(草图)。假设您将动画对组合到结构中,将它们作为单个值使用,那么您可以使用 .animation(_, value:)
为每个值指定专用动画:
@State private var pair: CGSize = .zero
@State private var phase: CGFloat = .zero
...
SineWaveShape(phase: phase, amplitude: amplitude, frequency: frequency)
.stroke(style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
.foregroundColor(.red)
.animation(Animation.linear(duration: 5).repeatForever(), value: phase)
.animation(Animation.spring(response: 0.5, dampingFraction: 0.4, blendDuration: 0.1).repeatForever(), value: pair)
.onAppear {
self.phase = 90
self.pair = CGSize(width: 0.1, height: 4)
}
关于SwiftUI - 使用不同曲线为多个参数设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62630729/