You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI设备方向切换时形状缩放阴影动画不同步问题

SwiftUI 设备方向旋转时自定义绘制阴影与圆盘视图动画不同步问题

问题现象

设备方向变化触发布局尺寸调整动画时,通过Path自定义绘制的阴影形状无法和同层级圆盘视图保持同步动画效果,会出现动画速率不匹配、视图错位的异常。

  • 异常静态效果截图:
    方向旋转时阴影错位静态效果
  • 异常动效演示:
    阴影与圆盘动画不同步动态效果

复现方式

以下代码可在iPad设备上切换横竖屏方向稳定复现该问题:

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                PlanetView()
                    .frame(width: geometry.size.width * 0.25, height: geometry.size.width * 0.25)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

struct PlanetView: View {
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                Circle()
                    .fill(.blue)

                Circle()
                    .foregroundColor(.green)
                    .overlay(PlanetShadowView())
                    .frame(width: geometry.size.width * 0.8, height: geometry.size.width * 0.8)
            }
        }
    }
}

struct PlanetShadowView: View {
    var offsetRatio: CGFloat = 15/100.0
    
    func control1(_ size: CGSize) -> CGPoint {
        let xOffset = offsetRatio * size.width
        let yOffset = offsetRatio * size.height
        return .init(x: xOffset, y: size.height - yOffset)
    }

    func control2(_ size: CGSize) -> CGPoint {
        let xOffset = offsetRatio * size.width
        let yOffset = offsetRatio * size.height
        return .init(x: size.width - xOffset, y: size.height - yOffset)
    }
    
    var body: some View {
        GeometryReader { geometry in
            Path { path in
                path.move(to: CGPoint(x: 0, y: geometry.size.height / 2))
                path.addCurve(to: CGPoint(x: geometry.size.width, y: geometry.size.height / 2),
                              control1: control1(geometry.size),
                              control2: control2(geometry.size))
                path.addArc(center: CGPoint(x: geometry.size.width / 2, y: geometry.size.height / 2),
                            radius: geometry.size.width / 2,
                            startAngle: Angle(degrees: 0),
                            endAngle: Angle(degrees: 180),
                            clockwise: false)
                path.closeSubpath()
            }
            .fill(Color.black.opacity(0.25))
            .rotationEffect(.degrees(-30))
        }
    }
}

struct PlanetView_Previews: PreviewProvider {
    static var previews: some View {
        PlanetView()
    }
}

初步排查结论

该异常由ContentView的布局逻辑直接导致:移除最外层GeometryReader、改用固定尺寸frame即可修复该动画同步异常。


内容的提问来源于stack exchange,提问作者Arnaud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:49:13