After I apply a rotation3DEffect
, my button keeps the decreased opacity you get when clicking a button. Googling I found this Reddit post which seems to be identical to what I'm experiencing: https://www.reddit.com/r/SwiftUI/comments/fb03c1/weird_glitch_after_rotation3deffect_animation/
Has anyone seen this before? Is there a way to fix it without taking away the Button?
My full code. Note this occurs even if I completely remove the .opacity
modifiers.
import SwiftUI
struct ContentView: View {
@State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
@State private var correctAnswer = Int.random(in: 0...2)
@State private var showingScore = false
@State private var scoreTitle = ""
@State private var correct = 0
@State private var asked = 0
@State private var hasGuessed = false
private var score: String {
"\(correct)/\(asked)"
}
var body: some View {
ZStack {
LinearGradient(gradient: Gradient(colors: [.blue, .black]), startPoint: .top, endPoint: .bottom)
.edgesIgnoringSafeArea(.all)
VStack(spacing: 30) {
VStack {
Text("Tap the flag of")
.foregroundColor(.white)
Text(countries[correctAnswer])
.foregroundColor(.white)
.font(.largeTitle)
.fontWeight(.black)
}
ForEach(0 ..< 3) { number in
Button(action: {
flagTapped(number)
}) {
FlagView(country: countries[number], isCorrect: correctAnswer == number, hasGuessed: hasGuessed)
}
}
Text("Score \(score)")
.foregroundColor(.white)
Spacer()
}
}
.alert(isPresented: $showingScore) {
Alert(
title: Text(scoreTitle),
message: Text("Your score is \(score)."),
dismissButton: .default(Text("Continue")) {
askQuestion()
}
)
}
}
func flagTapped(_ number: Int) {
if number == correctAnswer {
scoreTitle = "Correct"
correct += 1
} else {
scoreTitle = "Wrong! That's \(countries[number])."
}
asked += 1
hasGuessed = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
showingScore = true
}
}
func askQuestion() {
countries.shuffle()
correctAnswer = Int.random(in: 0...2)
hasGuessed = false
}
}
struct FlagView: View {
let country: String
let isCorrect: Bool
let hasGuessed: Bool
var body: some View {
Image(country)
.renderingMode(.original)
.clipShape(Capsule())
.overlay(Capsule().stroke(Color.black, lineWidth: 1))
.shadow(color: .black, radius: 2)
.rotation3DEffect(.degrees(hasGuessed && isCorrect ? 360 : 0), axis: (x: 0.0, y: 1.0, z: 0.0))
.animation(hasGuessed && isCorrect ? .easeInOut(duration: 1) : nil)
.opacity(hasGuessed && !isCorrect ? 0.25 : 1)
.animation(.easeInOut(duration: 1))
}
}