matchGeometryEffect并不总是为位置变化设置动画

问题描述

我的目标是模拟从正方形跳到正方形的棋子。

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
                            }
                        }
                }
            }
        }
    }
}

animations

单击1-从位置0到位置1:确定
单击2-从位置1到位置2:确定
单击3-从位置3到位置0:KO
单击4-从位置0到位置1:确定
单击5-从位置1到位置2:确定
单击6-从位置3到位置0:KO
单击7-从位置0到位置1:确定
...

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

如果在同一个事务中插入一个视图,并且删除了另一个具有相同键的视图,则系统将在窗口空间中插入其框架矩形,以使似乎有一个视图从其旧位置移动到新位置

我想念什么吗?
有什么限制吗?

Xcode版本12.1(12A7403) iOS 14.0

解决方法

这里有一个细微的修改,使其可以工作。无需将图像添加到具有不同不透明度的所有3个正方形上,而只需在当前包含典当的那个正方形上绘制图像即可。使用if current == i { }执行此操作。如果这样做,则可以仅将1用作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
                                }
                            }
                    }
                }
            }
        }
    }
}

在模拟器中:

simulator demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...