Swift UI 动画 360 度旋转

Posted

技术标签:

【中文标题】Swift UI 动画 360 度旋转【英文标题】:Swift UI animation 360 degree spin 【发布时间】:2021-07-06 14:15:15 【问题描述】:

早安,

我有一个标志程序,并希望添加动画,以便当点击正确的标志时,它会在 y 轴上旋转 360 度。

我可以编写代码并使所有 3 个标志旋转,无论是否点击了正确的标志,通过在“ForEach”下编写代码但是当我尝试在函数 flagTapped 下编写代码时失败,其中 if编写的子句确定数字是否 == 正确答案。这就是我觉得需要编写代码的地方。任何帮助将非常感激。代码如下:

导入 SwiftUI

结构内容视图:查看

@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()


【问题讨论】:

【参考方案1】:

重构您的代码,让事情变得更简单。

struct FlagButton: View 
    var country: String
    var onTap: () -> ()
    var body: some View 
        Button(action: 
            self.onTap()
        ) 
            Image(country)
                .renderingMode(.original)
                .clipShape(Capsule())
                .overlay(Capsule().stroke(Color.black, lineWidth: 1))
                .shadow(color: .black, radius: 2)
         
    


ForEach使用它

FlagButton(country: self.countries[number]) 
      flagTapped(number)


在您的代码中,如果答案正确,您将在 Button on tap 内添加一个新按钮。 SwiftUI 是错误的。从flagTapped 中删除按钮。你不需要使用它。如果答案正确,您只需旋转它即可。

    func flagTapped(_ number: Int) 
        if number == correctAnswer 
            scoreTitle = "Correct"
            score += 100
            withAnimation 
                self.animationAmount += 360
            
         else 
            scoreTitle = "Wrong. This was the flag of \(countries[number])"
            score -= 100
        
        showingScore = true
    

FlagButton 上使用rotation3DEffect 修饰符。

如果答案正确,请旋转。否则,不要。

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

你的所有代码!

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
                    FlagButton(country: self.countries[number]) 
                        flagTapped(number)
                    
                    .rotation3DEffect(.degrees(number == correctAnswer ? animationAmount: 0), axis: (x: 0, y: 1, z: 0))
                
                Spacer()
            
        
        .alert(isPresented: $showingScore) 
            Alert(title: Text(scoreTitle), message: Text("Your score is \(score)"), dismissButton: .default(Text("Continue")) 
                self.askQuestion()
            )
        
    
    
    
    func askQuestion() 
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
    
    
    func flagTapped(_ number: Int) 
        if number == correctAnswer 
            scoreTitle = "Correct"
            score += 100
            withAnimation 
                self.animationAmount += 360
            
         else 
            scoreTitle = "Wrong. This was the flag of \(countries[number])"
            score -= 100
        
        showingScore = true
    


struct FlagButton: View 
    var country: String
    var onTap: () -> ()
    var body: some View 
        Button(action: 
            self.onTap()
        ) 
            Image(country)
                .renderingMode(.original)
                .clipShape(Capsule())
                .overlay(Capsule().stroke(Color.black, lineWidth: 1))
                .shadow(color: .black, radius: 2)
        
    


【讨论】:

以上是关于Swift UI 动画 360 度旋转的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中无限期旋转 360 度视图?

使用 CSS3 动画将元素旋转到 360 度

如何用css3实现360度旋转动画

3dsmax如何让动画中物体角度的旋转大于360度?也就是能转很多圈?

Swift--使图片360° 周期旋转

CSS3 从 0 旋转到 90,然后从 90 旋转到 180