Button Swiftui-只需旋转所选按钮

Button Swiftui-只需旋转所选按钮,button,swiftui,Button,Swiftui,我正在跟随swift()的100天swift课程。项目6挑战1要求“返回猜测标志项目并添加一些动画:当您点击正确的标志时,使其在Y轴上旋转360度”。 当选择正确答案时,我能够使按钮旋转,但我不知道如何仅使所选按钮旋转 这是创建按钮的循环: ForEach(0..<3){ number in Button(action:{ self.flagTapped(number)

我正在跟随swift()的100天swift课程。项目6挑战1要求“返回猜测标志项目并添加一些动画:当您点击正确的标志时,使其在Y轴上旋转360度”。 当选择正确答案时,我能够使按钮旋转,但我不知道如何仅使所选按钮旋转

这是创建按钮的循环:

 ForEach(0..<3){ number in
                
                Button(action:{
                    self.flagTapped(number)
                }){
                    FlagImage(number: number, countries: self.countries)
                }
                .rotation3DEffect(.degrees(self.animationAmount), 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 showingMessage = false
@State private var scoreTitle = ""
@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)
            .edgesIgnoringSafeArea(.all)
        VStack (spacing:30){
            VStack{
                Text("Tap the flag of")
                    .foregroundColor(.white)
                Text(countries[correctAnswer])
                    .font(.largeTitle)
                    .fontWeight(.black)
                    .foregroundColor(.white)
            }
            
            ForEach(0 ..< 3) { number in
                
                if number == self.correctAnswer {
                    Button(action: {
                        self.flagTapped(number)
                    }) {
                        FlagImage(number: number, countries: self.countries)
                    }
                    .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 0, y: 1, z: 0))
                } else {
                    Button(action: {
                        self.flagTapped(number)
                    }) {
                        FlagImage(number: number, countries: self.countries)
                    }
                    .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 1, y: 0, z: 0))
                }
            }
            Text("Your score is \(score)")
                .foregroundColor(.white)
            Spacer()
        }
    }
    .alert(isPresented: $showingMessage){
        Alert(title: Text(scoreTitle), message: Text(""), dismissButton: .default(Text("Continue")){
            self.askQuestion()
        })
    }
}

func flagTapped(_ number: Int){
    if number == correctAnswer{
        scoreTitle = "Correct"
        self.score += 1
        withAnimation() {
            self.animationAmount += 360
        }
    }
    else{
        scoreTitle = "Wrong. That is the flag of \(self.countries[number])"
        self.score -= 1
        withAnimation() {
            self.animationAmount += 360
        }
    }
    showingMessage = true
}

func askQuestion(){
    countries.shuffle()
    correctAnswer = Int.random(in: 0...2)
}
}

struct FlagImage: View {
var number: Int
var countries:[String]=[]

var body: some View {
    Image(countries[number])
    .renderingMode(.original)
    .clipShape(Capsule())
    .overlay(Capsule().stroke(Color.black, lineWidth: 1))
    .shadow(color: .black, radius: 2)
}
}
struct ContentView:View{
@国家/私营var国家=[“爱沙尼亚”、“法国”、“德国”、“爱尔兰”、“意大利”、“尼日利亚”、“波兰”、“俄罗斯”、“西班牙”、“英国”、“美国”]。shuffled()
@国家私有变量correctAnswer=Int.random(in:0…2)
@State private var showingMessage=false
@国家私有var scoreTitle=“”
@国有私营企业风险值得分=0
@国家私有var animationAmount=0.0
var body:一些观点{
ZStack{
LinearGradient(渐变:渐变(颜色:[.蓝色,.黑色]),起点:.顶部,终点:.底部)
.edgesIgnoringSafeArea(.all)
VStack(间距:30){
VStack{
文本(“点击的标志”)
.foregroundColor(.白色)
文本(国家[答复])
.font(.largeTitle)
.fontWeight(.黑色)
.foregroundColor(.白色)
}
ForEach(0..<3){
如果数字==自我更正答案{
按钮(操作:{
自动标记(编号)
}) {
FlagImage(编号:编号,国家:self.countries)
}
.rotation3DEffect(.degrees(self.animationAmount),轴:(x:0,y:1,z:0))
}否则{
按钮(操作:{
自动标记(编号)
}) {
FlagImage(编号:编号,国家:self.countries)
}
.rotation3DEffect(.degrees(self.animationAmount),轴:(x:1,y:0,z:0))
}
}
文本(“您的分数是\(分数)”)
.foregroundColor(.白色)
垫片()
}
}
.警报(显示:$showingMessage){
警报(标题:文本(scoreTitle),消息:文本(“”),dismissButton:。默认值(文本(“继续”)){
self.askQuestion()
})
}
}
func flagstapped(uu编号:Int){
如果数字==正确答案{
scoreTitle=“正确”
self.score+=1
withAnimation(){
self.animationAmount+=360
}
}
否则{
scoreTitle=“错误。这是\(self.countries[编号])的标志)
自我评分-=1
withAnimation(){
self.animationAmount+=360
}
}
showingMessage=true
}
func askQuestion(){
国家。洗牌()
correctAnswer=Int.random(in:0…2)
}
}
结构FlagImage:视图{
变量编号:Int
变量国家:[字符串]=[]
var body:一些观点{
图像(国家[编号])
.renderingMode(.original)
.clipShape(胶囊())
.overlay(胶囊().stroke(颜色.黑色,线宽:1))
.阴影(颜色:。黑色,半径:2)
}
}

您正在将
.rotation3DEffect
应用于每个按钮,但在更改
self.animationmount
之前,动画不会发生

对于
正确答案
,只能使用
self.animationAmount

更改:

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


另一种方法是:(唉,这似乎只适用于Xcode 12b5):


代码的最小修复:

现在,我已经确定了为什么这在Xcode 11.6中不起作用,下面是对代码进行的最小更改:

  • 更改
    ForEach
    循环,以迭代包含
    (偏移量,元素)
    的元组的
    数组
    ,并通过添加
    ,id:\.element
    将国家名称用作
    id
    。由于国家名称是唯一的,这有助于确保国旗在更改时更新
  • 在闭包中,选择元组的各个部分,并将它们称为
    number
    name
    ,以清晰地显示
  • 将带有按钮的
    if
    语句放在
    组{}
    中,因为Xcode 11.6中的SwiftUI无法单独处理
    if

  • 第二个选项无法按预期工作。我希望它能工作,但我不知道出了什么问题。它不再为按钮设置动画。另外,我没有重新加载标志(屏幕上总是显示相同的标志),我只是发布了整个代码。你能看一下吗?谢谢很抱歉删除了正确的答案。我试图在后续评论中遵循堆栈溢出的指导原则。我在第一个按钮上看到了你的动画。我的后续评论是指您的第二个选项,其中的按钮包含在“if-else”语句中。我想要其他按钮的第二个动画(如果你注意到,我更改了非选定按钮的x和y值)版本11.6(11E708)我正在运行你的代码,并且旗帜图像在新游戏中不会更改。你看到那种行为了吗?
    .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 0, y: 1, z: 0))
    
    .rotation3DEffect(.degrees(number == correctAnswer ? self.animationAmount : 0), axis: (x: 0, y: 1, z: 0))
    
    ForEach(0 ..< 3) { number in
        if number == correctAnswer {
            Button(action: {
                self.flagTapped(number)
            }) {
                FlagImage(number: number, countries: self.countries)
            }
            .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 0, y: 1, z: 0))
        } else {
            Button(action: {
                self.flagTapped(number)
            }) {
                FlagImage(number: number, countries: self.countries)
            }
        }
    }
    
    struct FlagImage: View {
        var country: String
        
        var body: some View {
            Image(country)
                .renderingMode(.original)
                .clipShape(Capsule())
                .overlay(Capsule().stroke(Color.black, lineWidth: 1))
                .shadow(color: .black, radius: 2)
        }
    }
    
    struct Flag: Identifiable {
        let id = UUID()
        let country: String
    }
    
    struct ContentView: View {
        @State private var showingScore = false
        @State private var scoreTitle = ""
        
        @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled().map(Flag.init)
        @State private var correctAnswer = Int.random(in: 0...2)
        @State private var score = 0
        @State private var alertMessage = ""
        @State private var animationAmount = 0.0
        @State private var animatedOpacity = 1.0
        
        var body: some View {
            ZStack {
                    LinearGradient(gradient: Gradient(colors: [.blue, .black]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all)
                VStack {
                    VStack {
                        Text("Tap the flag of ").foregroundColor(.white)
                        Text("\(countries[correctAnswer].country) ")
                            .foregroundColor(.white)
                            .font(.largeTitle)
                            .fontWeight(.black)
                    }
                    
                    ForEach(countries.prefix(3)) { flag in
                        Group {
                            if flag.country == self.countries[self.correctAnswer].country {
                                Button(action: {
                                    self.flagTapped(flag.country)
                                }) {
                                    FlagImage(country: flag.country)
                                }
                                .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 0, y: 1, z: 0))
                            } else {
                                Button(action: {
                                    self.flagTapped(flag.country)
                                }) {
                                    FlagImage(country: flag.country)
                                }
                                .opacity(self.animatedOpacity)
                            }
                        }
                    }
                    
                    Text("Score: \(score)").foregroundColor(.white)
                    
                    Spacer()
                }
            }
            .alert(isPresented: $showingScore) {
                Alert(title: Text(scoreTitle), message: Text(alertMessage), dismissButton: .default(Text("Continue")) {
                    self.askQuestion()
                })
            }
        }
        
        func flagTapped(_ country: String) {
            if country == countries[correctAnswer].country {
                score += 1
                scoreTitle = "Correct!"
                alertMessage = "Your score is now \(score)"
                withAnimation {
                    animationAmount += 360
                    animatedOpacity = 0
                }
            } else {
                scoreTitle = "Wrong."
                alertMessage = "That is the flag of \(country)"
                score -= 1
            }
            
            showingScore = true
        }
        
        func askQuestion() {
            countries.shuffle()
            correctAnswer = Int.random(in: 0...2)
            self.animatedOpacity = 1.0
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
        ForEach(Array(self.countries.prefix(3).enumerated()), id: \.element) { number, name in
            Group {
                if number == self.correctAnswer {
                    Button(action: {
                        self.flagTapped(number)
                    }) {
                        FlagImage(number: number, countries: self.countries)
                    }
                    .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 0, y: 1, z: 0))
                } else {
                    Button(action: {
                        self.flagTapped(number)
                    }) {
                        FlagImage(number: number, countries: self.countries)
                    }
                    .rotation3DEffect(.degrees(self.animationAmount), axis: (x: 1, y: 0, z: 0))
                }
            }
        }