iOS15中SwiftUI Image动画锚点异常(非中心而是左上角)
问题修复:iOS15中SwiftUI心跳动画锚点异常
问题分析
在iOS15及以下版本中,你的代码出现两个核心问题:
- 锚点偏移:
scaleEffect的.center锚点未生效,动画以图片左上角为基准,这是因为iOS15中SwiftUI对视图布局优先级的处理与iOS16不同,frame和aspectRatio的顺序导致视图的几何中心计算错误。 - 动画作用范围错误:动画作用于整个
VStack而非图片本身,原因是VStack未被约束为占满父视图,导致系统将动画的布局上下文绑定到了VStack的自适应边界上。
修复方案
1. 调整视图层级与布局约束
- 让
LoadingView的VStack占满整个屏幕,确保图片处于绝对中心 - 调整
Image的修饰符顺序,先设置内容填充模式,再约束尺寸并裁剪,保证图片在固定帧内居中 - 明确动画触发时机,避免视图未完成布局就启动动画
2. 优化动画触发逻辑
使用task修饰符替代onAppear,确保视图完全布局后再启动动画,避免iOS15中的布局竞态问题
修改后的完整代码
LoadingView 修复版
struct LoadingView: View{ @State private var animatingLogo = false var body: some View{ VStack(alignment: .center, spacing: 6) { Image("JHLogo") .aspectRatio(contentMode: .fill) .frame(width: 200, height: 200) .clipped() // 裁剪超出frame的图片部分 .scaleEffect(animatingLogo ? 0.15 : 0.1, anchor: .center) } .frame(maxWidth: .infinity, maxHeight: .infinity) // 让VStack占满父视图 .navigationBarHidden(true) .task { // 视图布局完成后启动动画 withAnimation(.easeInOut(duration: 1).repeatForever()) { animatingLogo.toggle() } } } }
MainView 修复版
// Initial view that is loaded on app startup struct MainView: View{ @State private var isLoading = false var body : some View { NavigationView { if isLoading { LoadingView() } else { CoverPageView() } } .onAppear { startLoadingScreen() } } func startLoadingScreen() { isLoading = true DispatchQueue.main.asyncAfter(deadline: .now() + 3) { isLoading = false } } }
额外优化建议
如果上述修复仍有问题,可以尝试用transformEffect替代scaleEffect,手动控制缩放中心,兼容性更好:
.transformEffect(CGAffineTransform(scaleX: animatingLogo ? 0.15 : 0.1, y: animatingLogo ? 0.15 : 0.1))
内容的提问来源于stack exchange,提问作者philm
相关产品推荐
相关产品推荐

