如何在matchedGeometryEffect中实现旋转过渡效果?
问题描述
垂直或水平移动Rectangle时,matchedGeometryEffect可正常工作,但在垂直与水平位置模式间切换时,我需要添加旋转过渡效果却无法实现,目前使用的scale过渡无法解决该问题。如何在垂直与水平位置切换时实现旋转过渡效果?

当前代码
struct ContentView: View { @StateObject var myClass: MyClass = MyClass.shared var body: some View { VStack { MyView() .frame(width: 300.0, height: 300.0) .background(Color.red).cornerRadius(20.0) HStack { Button("top") { myClass.position = .top } Spacer() Button("bottom") { myClass.position = .bottom } Spacer() Button("left") { myClass.position = .left } Spacer() Button("right") { myClass.position = .right } } .frame(width: 300.0) } .padding() } } enum Position: String { case top, bottom, left, right } class MyClass: ObservableObject { static let shared: MyClass = MyClass() @Published var position: Position = Position.bottom } struct MyView: View { @StateObject var myClass: MyClass = MyClass.shared @Namespace var matchedGeometryEffectOfRectangle var body: some View { VStack { switch myClass.position { case .top: VStack { Color.blue.frame(height: 50.0).cornerRadius(10.0) .matchedGeometryEffect(id: "Rectangle", in: matchedGeometryEffectOfRectangle) .transition(.scale(scale: 1, anchor: .center)) Spacer() } case .bottom: VStack { Spacer() Color.blue.frame(height: 50.0).cornerRadius(10.0) .matchedGeometryEffect(id: "Rectangle", in: matchedGeometryEffectOfRectangle) .transition(.scale(scale: 1, anchor: .center)) } case .left: HStack { Color.blue.frame(width: 50.0).cornerRadius(10.0) .matchedGeometryEffect(id: "Rectangle", in: matchedGeometryEffectOfRectangle) .transition(.scale(scale: 1, anchor: .center)) Spacer() } case .right: HStack { Spacer() Color.blue.frame(width: 50.0).cornerRadius(10.0) .matchedGeometryEffect(id: "Rectangle", in: matchedGeometryEffectOfRectangle) .transition(.scale(scale: 1, anchor: .center)) } } } .padding() .animation(.default, value: myClass.position) } }
解决方案
要实现垂直/水平切换时的旋转过渡,需解决视图尺寸突变、旋转与位置动画协同的问题,具体实现如下:
修改核心逻辑
- 统一视图尺寸:给蓝色矩形设置固定50x50的宽高,避免垂直/水平模式切换时的尺寸突变。
- 动态旋转角度:根据当前位置给矩形添加对应旋转角度,水平位置时旋转90度,模拟横向显示效果。
- 简化布局结构:用
ZStack替代多组VStack/HStack,通过偏移控制矩形位置,配合matchedGeometryEffect实现平滑过渡。 - 统一动画控制:移除局部
transition,通过全局动画同步位置和旋转的过渡效果。
修改后的MyView代码
struct MyView: View { @StateObject var myClass: MyClass = MyClass.shared @Namespace var matchedGeometryEffectOfRectangle // 根据位置计算旋转角度 private var rotationAngle: Angle { switch myClass.position { case .top, .bottom: return .degrees(0) case .left: return .degrees(-90) case .right: return .degrees(90) } } // 根据位置计算偏移,适配父容器位置 private var offset: CGSize { switch myClass.position { case .top: return CGSize(width: 0, height: -100) case .bottom: return CGSize(width: 0, height: 100) case .left: return CGSize(width: -100, height: 0) case .right: return CGSize(width: 100, height: 0) } } var body: some View { ZStack { Color.blue.frame(width: 50, height: 50) .cornerRadius(10) .matchedGeometryEffect(id: "Rectangle", in: matchedGeometryEffectOfRectangle) .rotationEffect(rotationAngle) .offset(offset) } .padding() .animation(.easeInOut(duration: 0.5), value: myClass.position) } }
效果说明
修改后,垂直/水平位置切换时,蓝色矩形会同时完成位置移动和旋转的平滑过渡,解决了原方案中无法实现旋转效果的问题。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

