SwiftUI - 如何为数组元素对应的组件设置动画?

SwiftUI - How to animate components corresponding to array elements?

我在SwiftUI中有一个圆的HStack,圆的个数是根据数组的长度来决定的,像这样:

@State var myArr = [...]
...
ScrollView(.horizontal) {
  HStack {
    ForEach(myArr) { item in
      Circle()
      //.frame(...)
      //.animation(...) I tried this, it didn't work
    }
  }
}

然后我有一个按钮可以将一个元素附加到这个数组,有效地向视图添加一个圆圈:

Button {
  myArr.append(...)
} label: {
  ...
}

该按钮按预期工作,但是,添加到视图中的新圆圈出现得非常突然,而且看起来很不稳定。我怎样才能以任何方式制作动画?也许它从侧面滑入,或者从一个很小的圆圈长到正常大小。

您缺少转换,这是您要查找的内容:

 struct ContentView: View {
    
    @State private var array: [Int] = Array(0...2)
    
    var body: some View {
        
        ScrollView(.horizontal) {
            HStack {
                ForEach(array, id:\.self) { item in
                    
                    Circle()
                        .frame(width: 50, height: 50)
                        .transition(AnyTransition.scale)
                    
                }
            }
        }
        .animation(.default, value: array.count)
        
        
        Button("add new circle") {
            array.append(array.count)
        }
        
        Button("remove a circle") {
            if array.count > 0 {
                array.remove(at: array.count  - 1)
            }
        }
 
    }
}

自动滚动到最后一个圆圈的版本:

struct myItem: Identifiable, Equatable {
    let id = UUID()
    var size: CGFloat
}

struct ContentView: View {
    
    @State private var myArr: [myItem] = [
        myItem(size: 10),
        myItem(size: 40),
        myItem(size: 30)
    ]
    
    var body: some View {
        
        ScrollViewReader { scrollProxy in
            VStack(alignment: .leading) {
                Spacer()
                
                ScrollView(.horizontal) {
                    HStack {
                        ForEach(myArr) { item in
                            Circle()
                                .id(item.id)
                                .frame(width: item.size, height: item.size)
                                .transition(.scale)
                        }
                    }
                }
                .animation(.easeInOut(duration: 1), value: myArr)
                
                Spacer()
                
                Button("Add One") {
                    let new = myItem(size: CGFloat.random(in: 10...100))
                    myArr.append(new)
                }
                
                .onChange(of: myArr) { _ in
                    withAnimation {
                        scrollProxy.scrollTo(myArr.last!.id, anchor: .trailing)
                    }
                }
                
                .frame(maxWidth: .infinity, alignment: .center)
            }
            .padding()
        }
    }
}