matchedGeometryEffect 的动画效果不流畅

az2*_*902 5 ios swift swiftui

我正在尝试做一个简单的事情matchedGeometryEffect,但它不起作用。我有一个Image具有固定框架的简单动画,我想将其动画化为Image占据整个屏幕的动画。这就是现在的样子,正如您所看到的,它的过渡并不顺利:

在此输入图像描述

这是我的代码:

struct ContentView: View {
    @State private var enlarged = false
    @Namespace private var animation
    
    var body: some View {
        ZStack {
            if (enlarged) {
                Image("dunes")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .matchedGeometryEffect(id: "image", in: animation)
                    .ignoresSafeArea(.all, edges: .all)
            } else {
                Image("dunes")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .matchedGeometryEffect(id: "image", in: animation)
                    .frame(width: 300, height: 225)

            }
        }
        .onTapGesture {
            withAnimation {
                enlarged.toggle()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Rol*_*tte 11

为了使matchedGeometryEffect动画顺利进行,您几乎不需要遵循一些规则。您必须在 后声明框架matchedGeometryEffect。动画必须放置在每个图像的末尾,而不是放在.tapGesture.

这是经过修改的代码:

struct ContentView: View {

  @State private var enlarged = false
  @Namespace private var namespace

  var body: some View {
    ZStack {
      if enlarged {
        Image("dunes")
          .resizable()
          .matchedGeometryEffect(id: "image", in: namespace)
          .aspectRatio(contentMode: .fill)
          .ignoresSafeArea(.all, edges: .all)
          .animation(.easeInOut)
      }
      else {
        Image("dunes")
          .resizable()
          .matchedGeometryEffect(id: "image", in: namespace)
          .aspectRatio(contentMode: .fill)
          .frame(width: 300, height: 225)
          .animation(.easeInOut)

      }
    }
    .onTapGesture { enlarged.toggle() }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • matchedGeometryEffect 是一个非常好的工具,但它有缺陷并且需要改进,而且正如大多数 Apple 文档一样,并不是所有内容都可以在其中找到。规则是您想要包含在过渡中的所有修改器和视图都必须放在matchedGeometryEffect 之前。在这种情况下,两个视图不共享同一帧,因此必须是 after。至于动画,我喜欢让它们尽可能靠近它们所依赖的视图,以避免意外的相关子视图被动画化。它在 ZStack 上的工作方式相同,但在按钮中触发时则不然。 (2认同)