何かの状態に基づいてアニメーションの色を変更しようとしています。色の変更は機能しますが、前の(オレンジ)色をアニメートします。両方の色が表示されている理由がよくわかりません。何か案は?
struct PulsatingView: View {
var state = 1
func colourToShow() -> Color {
switch state {
case 0:
return Color.red
case 1:
return Color.orange
case 2:
return Color.green
default:
return Color.orange
}
}
@State var animate = false
var body: some View {
VStack {
ZStack {
Circle().fill(colourToShow().opacity(0.25)).frame(width: 40, height: 40).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.35)).frame(width: 30, height: 30).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.45)).frame(width: 15, height: 15).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow()).frame(width: 6.25, height: 6.25)
}
.onAppear { self.animate.toggle() }
.animation(Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true))
}
}
}
あなたは色を変更しますが、設定されているアニメーション表示foreverは変更されません-設定されたままで、指定されたとおりに継続します-永久に。したがって、アニメーションを再設定する必要があります。
動作しているフルモジュールのデモコードを以下に示します(Xcode 11.2/iOS 13.2でテスト済み)。考え方は、ObservableObject
ビューモデルを使用してビューを更新し、受信時にいくつかのアクションを実行することです。したがって、色の変更を受信すると、色とアニメーションをリセットして表示できます。
import SwiftUI
import Combine
class PulsatingViewModel: ObservableObject {
@Published var colorIndex = 1
}
struct PulsatingView: View {
@ObservedObject var viewModel: PulsatingViewModel
func colourToShow() -> Color {
switch viewModel.colorIndex {
case 0:
return Color.red
case 1:
return Color.orange
case 2:
return Color.green
default:
return Color.orange
}
}
@State var animate = false
var body: some View {
VStack {
ZStack {
Circle().fill(colourToShow().opacity(0.25)).frame(width: 40, height: 40).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.35)).frame(width: 30, height: 30).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.45)).frame(width: 15, height: 15).scaleEffect(self.animate ? 1 : 0)
Circle().fill(colourToShow()).frame(width: 6.25, height: 6.25)
}
.onAppear { self.animate = true }
.animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : .default)
.onReceive(viewModel.$colorIndex) { _ in
self.animate = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.animate = true
}
}
}
}
}
struct TestPulseColorView: View {
private var model = PulsatingViewModel()
var body: some View {
VStack {
Spacer()
PulsatingView(viewModel: model)
Spacer()
Button("Toggle") { self.model.colorIndex = Int.random(in: 0...2) }
}
}
}
struct TestPulseColorView_Previews: PreviewProvider {
static var previews: some View {
TestPulseColorView()
}
}