UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Animation: Guess the flag question

Forums > SwiftUI

hi there,

the exercise objective is to:

tap the correct flag, make it spin around 360 degrees on the Y axis.

so, am having trouble figuring out how to write the code in order to make the correct flag spin. The code worked successfully when I wrote it under ForEach, but that made all 3 flags spin, regardless of whether the answer was correct or not. Knowing that, I believed it necessary to write the code below the if clause in func flagTapped. This is where it went wrong, and I'm unsuccessful in resolving the errors. Appreciate any guidance...

struct ContentView: View {
 @ State private var animationAmount = 0.0
func flagTapped(_ number: Int) {

        if number == correctAnswer {

            scoreTitle = "Correct"

            score += 100

            Button() {

                withAnimation {

                    self.animationAmount += 360

                }

            }

            .rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))

        } else {

            scoreTitle = "Wrong. This was the flag of \(countries[number])"

            score -= 100

        }

        showingScore = true

3      

Have a link to the repo?

3      

Apologies for not including the full code

https://github.com/taylorpad32/taylor-SwiftUI/blob/main/GuessTheFlag/GuessTheFlag/ContentView.swift

or below....


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 // tells us if alert is showing or not

    @State private var scoreTitle = "" // title inside the alert

    @State private var score = 0

    @State private var animationAmount = 0.0

    var body: some View {

        ZStack {

            LinearGradient(gradient: Gradient(colors: [.blue, .black]),

                           startPoint: .top, endPoint: .bottom)

            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: {

                        self.flagTapped(number)

                    }) {

                        Image(self.countries[number])

                            .renderingMode(.original)

                            .clipShape(Capsule())

                            .overlay(Capsule().stroke(Color.black, lineWidth: 1))

                            .shadow(color: .black, radius: 2)

                    }

                }

                Spacer()

            }

        }

        .alert(isPresented: $showingScore) {

            Alert(title: Text(scoreTitle), message: Text("Your score is \(score)"), dismissButton: .default(Text("Continue")) {

                self.askQuestion()

            })

        }

    }

    //======================================

    func flagTapped(_ number: Int) {

        if number == correctAnswer {

            scoreTitle = "Correct"

            score += 100

            Button() {

                withAnimation {

                    self.animationAmount += 360

                }

            }

            .rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))

        } else {

            scoreTitle = "Wrong. This was the flag of \(countries[number])"

            score -= 100

        }

        showingScore = true

    }

    //====================================

    func askQuestion() {

        countries.shuffle()

        correctAnswer = Int.random(in: 0...2)

    }

}

struct ContentView_Previews: PreviewProvider {

    static var previews: some View {

        ContentView()

    }

}

3      

I was just having the same issues you were. What I did was create a bool to track if the flag should be animating.

Next, you can move the withAnimation into your buttons actions. And you can use conditionals inside the withAnimation code. Something like this:

withAnimation((number == correctAnswer && animating) ? .interpolatingSpring(stiffness: 10, damping: 20) : .easeIn) {
                            animationAmount += 360
                        }

Then you can move the .rotation3D call into the label portion of the button and make it a modifier for your image. You can also you conditionals in this as well. Something like this:

.rotation3DEffect(.degrees((number == correctAnswer && animating) ? animationAmount : 0),
                            axis: (x: 0, y: 1, z: 0))

You can add the opacity modifier to the flag image as well with conditionals.

I'm sure there are better ways to do it. And you can change the animating effect to suite your tastes. But hopefully that helps you out a bit.

4      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.