SwiftUI对除.foregroundColor以外的所有对象设置动画

SwiftUI对除.foregroundColor以外的所有对象设置动画,swiftui,swiftui-animation,swiftui-state,Swiftui,Swiftui Animation,Swiftui State,基于@State var的值,如何设置除一个参数之外的任何其他参数的动画?例如,我想设置.offset的动画,但不想设置.foregroundColor的动画。这听起来似乎是一项容易的任务,但使用相同的“基本视图”创建某种单元视图并组合不同的修改器和转换时就不那么容易了 对于下面的动画,我试图“避免”在允许偏移发生的同时更改颜色动画-我需要立即更改颜色,而不是动画 对于这个动画,我还试图“避免”改变颜色的动画。这里的挑战是基本视图也有一个转换 “基本视图”名称为LogoView。这是我的密码

基于
@State var
的值,如何设置除一个参数之外的任何其他参数的动画?例如,我想设置
.offset
的动画,但不想设置
.foregroundColor
的动画。这听起来似乎是一项容易的任务,但使用相同的“基本视图”创建某种单元视图并组合不同的修改器和转换时就不那么容易了

对于下面的动画,我试图“避免”在允许偏移发生的同时更改颜色动画-我需要立即更改颜色,而不是动画

对于这个动画,我还试图“避免”改变颜色的动画。这里的挑战是基本视图也有一个转换

“基本视图”名称为
LogoView
。这是我的密码:

struct Test_ForegroundColorAnimation: View {
    var array: [Color] = [.yellow, .green, .blue]
    @State var activeIndex1: Int = -1
    @State var activeIndex2: Int = -1
    @State var show: Bool = true

    private func animationFor(index: Int) -> Animation {
        Animation
            .easeInOut(duration: 0.85)
            .delay(0.15 * Double(array.count - index))
    }

    func zindexfor(index: Int) -> Double {
        Double(index == activeIndex1 ? 100 : index)
    }

    func opacityfor(index: Int) -> Double {
        self.activeIndex1 >= 0 ? (index == self.activeIndex1 ? 1 : 0) : 1
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 25) {
            Spacer()

            VStack {
                Text("Offset animation").font(.title)
                Text("Click any item").font(.subheadline)
            }

            ZStack {
                ForEach(array.indices, id: \.self) { index in
                    LogoView(isSelected: index == self.activeIndex1, color: self.array[index])
                        .offset(x: self.activeIndex1 == -1 ? CGFloat(90 * index) : 0)
                        .zIndex(self.zindexfor(index: index))
                        .opacity(self.opacityfor(index: index))
                        .animation(self.animationFor(index: index))
                        .onTapGesture {
                            self.activeIndex1 = index == self.activeIndex1 ? -1 : index
                        }
                }
            }
            .padding(.bottom, 70)

            VStack {
                Text("Transition").font(.title)
                Text("Click any item").font(.subheadline)
            }

            Button(action: {
                self.show.toggle()
            }) {
                Color.purple
                    .frame(width: 100, height: 70)
                    .overlay(Text("Activate transition!").foregroundColor(.white))
            }

            HStack(spacing: 5) {
                ForEach(array.indices, id: \.self) { index in
                    HStack {
                        if self.show {
                            LogoView(isSelected: index == self.activeIndex2, color: self.array[index])
                                .transition(AnyTransition.move(edge: .bottom))
                                .onTapGesture {
                                    self.activeIndex2 = index == self.activeIndex2 ? -1 : index
                                }
                        }
                    }
                    .frame(width: 90, height: 90)
                    .animation(self.animationFor(index: index))
                }
            }
        }
    }
}

struct Test_ForegroundColorAnimation_Previews: PreviewProvider {
    static var previews: some View {
        Test_ForegroundColorAnimation()
    }
}

struct LogoView: View {
    var isSelected: Bool = false
    var color: Color = Color(#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1))
    var shadow: Color = Color(#colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1))

    var body: some View {
        Image(systemName: "heart.fill")
            .resizable()
            .frame(width: 28, height: 28)
            .foregroundColor(isSelected ? Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)) : color)
            .padding()
            .overlay(
                Circle()
                    .stroke(lineWidth: 3)
                    .foregroundColor(color)
            )
            .background(
                Circle()
                    .foregroundColor(isSelected ? color : Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
                    .shadow(color: isSelected ? color.opacity(0.7) : Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.3), radius: 5, x: 0, y: 10)
            )
            .frame(width: 90, height: 90)
    }
}

如果我正确理解了您的需求,这里有一个解决方案

struct LogoView:View{
var isSelected:Bool=false
变量颜色:颜色=颜色(#colorLiteral(红色:0.8078431487,绿色:0.02745098062,蓝色:0.3333333433,α:1))
var shadow:Color=Color(#colorLiteral(红色:0.439215899,绿色:0.01176470611,蓝色:0.19215682,alpha:1))
var body:一些观点{
图像(系统名称:“heart.fill”)
.可调整大小()
.框架(宽度:28,高度:28)
.foregroundColor(isSelected?颜色(#colorLiteral(红色:1,绿色:1,蓝色:1,alpha:1)):颜色)
.padding()
.覆盖(
圈()
.笔划(线宽:3)
.foregroundColor(颜色)
)
.背景(
圈()
.foregroundColor(isSelected?颜色:颜色(#colorLiteral(红色:1,绿色:1,蓝色:1,阿尔法:1)))
.动画(无)//
struct LogoView: View {
    var isSelected: Bool = false
    var color: Color = Color(#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1))
    var shadow: Color = Color(#colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1))

    var body: some View {
        Image(systemName: "heart.fill")
            .resizable()
            .frame(width: 28, height: 28)
            .foregroundColor(isSelected ? Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)) : color)
            .padding()
            .overlay(
                Circle()
                    .stroke(lineWidth: 3)
                    .foregroundColor(color)
            )
            .background(
                Circle()
                    .foregroundColor(isSelected ? color : Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
                    .animation(nil)                  // << fix !!
                    .shadow(color: isSelected ? color.opacity(0.7) : Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.3), radius: 5, x: 0, y: 10)
            )
            .frame(width: 90, height: 90)
    }
}