在swiftUI中创建星型动画时遇到问题

问题描述

我正在尝试使用模糊效果创建星星动画,但是星星最终消失了,我不知道为什么。 通过一点调试,我很确定这与我使用onAppear的方式有关。我只是在尝试确保星星永远在屏幕上模糊和模糊-我一直希望星星是可见的。

任何人都可以帮助我解决此问题(下面的代码),任何设计技巧都将受到赞赏,哈哈。

struct ContentView: View {
    @State private var radius = 2
    private var opacity = 0.25
    var body: some View {
        ZStack {
            Color.black.edgesIgnoringSafeArea(.all)
            vstack  {
                ForEach(0..<8) {_ in
                HStack {
                    ForEach(0..<5) { _ in
                        Circle().fill(Color.white)
                        .frame(width: 3,height: 3)
                        .blur(radius: CGFloat(self.radius))
                        .animation(Animation.easeInOut(duration: 6).
                        repeatForever(autoreverses: true))
                        .padding(EdgeInsets(top: self.calculaterandom(),leading: 0,bottom: 0,trailing: self.calculaterandom()))
                        .onAppear() {
                            self.radius += 2
                                
                        }
                }
                }
            }
            }
            
            
        }
    }
    
    func calculaterandom() -> CGFloat {
        return CGFloat(Int.random(in: 30..<150))
    }
}

解决方法

要激活动画,您需要切换一些值,因此动画师的动画范围必须介于两者之间。

这里是固定代码。在Xcode 12 / iOS 14上进行了测试。

demo

struct ContentView: View {
    @State private var run = false    // << here !!

    private var opacity = 0.25
    var body: some View {
        ZStack {
            Color.black.edgesIgnoringSafeArea(.all)
            VStack  {
                ForEach(0..<8) {_ in
                HStack {
                    ForEach(0..<5) { _ in
                        Circle().fill(Color.white)
                        .frame(width: 3,height: 3)
                        .blur(radius: run ? 4 : 2)     // << here !!
                        .animation(Animation.easeInOut(duration: 6).repeatForever(autoreverses: true))
                        .padding(EdgeInsets(top: self.calculateRandom(),leading: 0,bottom: 0,trailing: self.calculateRandom()))
                        .onAppear() {
                            self.run = true     // << here !!
                        }
                }
                }
            }
            }


        }
    }

    func calculateRandom() -> CGFloat {
        return CGFloat(Int.random(in: 30..<150))
    }
}

更新:具有静态 star 位置的变体(运动动画是由添加新元素后在V / H / Stack中的布局引起的,因此需要避免这种情况使用.position修饰符在ZStack中手动删除这些内部堆栈和布局)

demo2

struct BlurContentView: View {
    @State private var run = false
    
    var body: some View {
        ZStack {
            Color.black.edgesIgnoringSafeArea(.all)
            GeometryReader { gp in
                ForEach(0..<8) {_ in
                    ForEach(0..<5) { _ in
                        Circle().fill(Color.white)
                            .frame(width: 3,height: 3)
                            .position(x: calculateRandom(in: gp.size.width),y: calculateRandom(in: gp.size.height))
                            .animation(nil)     // << no animation for above modifiers
                            .blur(radius: run ? 4 : 2)
                        
                    }
                }
            }
            .animation(Animation.easeInOut(duration: 6)
                .repeatForever(autoreverses: true),value: run) // animate one value
            .onAppear() {
                self.run = true
            }
        }
    }
    
    func calculateRandom(in value: CGFloat) -> CGFloat {
        return CGFloat(Int.random(in: 10..<Int(value) - 10))
    }
}