0

我的目标是模拟一个从一个方块跳到另一个方块的棋子。

struct MyView: View {
    @State var current = 0;
    @State var colors : [Color] = [.blue, .gray, .red]
    @Namespace var animationNamespace : Namespace.ID
    var body : some View {
        HStack(spacing: 12){
            ForEach(colors.indices) { i in
                ZStack{
                    RoundedRectangle(cornerRadius: 8)
                        .fill(colors[i])
                        .frame(width: 50, height: 50)
                    Image(systemName: "person.crop.square")
                        .resizable()
                        .scaledToFit()
                        .cornerRadius(8)
                        .opacity(current == i ? 1.0 : 0.0)
                        .frame(width: 50, height: 50)
                        .matchedGeometryEffect(id: current == i ? -1 : i , in: animationNamespace)
                        .onTapGesture {
                            withAnimation(.easeInOut){
                                current = (current + 1) % colors.capacity
                            }
                        }
                }
            }
        }
    }
}

动画

点击 1 - 从位置 0 到位置 1:OK
点击 2 - 从位置 1 到位置 2:OK
点击 3 - 从位置 3 到位置 0:KO
点击 4 - 从位置 0 到位置 1:OK
点击 5 - 从位置 1到位置 2:OK
点击 6 - 从位置 3 到位置 0:KO
点击 7 - 从位置 0 到位置 1:OK
...

https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)

如果在同一事务中插入一个视图,而另一个具有相同键的视图被删除,系统将在窗口空间中插入它们的框架矩形,以使看起来有一个视图从其旧位置移动到其新位置。

我错过了什么吗?
有什么限制吗?

Xcode 版本 12.1 (12A7403) iOS 14.0

4

1 回答 1

1

这是使其工作的轻微修改。不要将图像添加到具有不同不透明度的所有 3 个正方形中,而只需在当前包含 pawn 的那个上绘制图像。使用if current == i { }. 如果你这样做,那么你可以使用1as matchedGeometryEffect id

struct ContentView: View {
    @State var current = 0;
    @State var colors : [Color] = [.blue, .gray, .red]
    @Namespace var animationNamespace : Namespace.ID
    var body : some View {
        HStack(spacing: 12){
            ForEach(colors.indices) { i in
                ZStack{
                    RoundedRectangle(cornerRadius: 8)
                        .fill(colors[i])
                        .frame(width: 50, height: 50)
                    if current == i {
                        Image(systemName: "person.crop.square")
                            .resizable()
                            .scaledToFit()
                            .cornerRadius(8)
                            .frame(width: 50, height: 50)
                            .matchedGeometryEffect(id: 1 , in: animationNamespace)
                            .onTapGesture {
                                withAnimation(.easeInOut){
                                    current = (current + 1) % colors.capacity
                                }
                            }
                    }
                }
            }
        }
    }
}

这是在模拟器中:

模拟器演示

于 2020-11-05T02:22:23.753 回答