The Util Designer
SwiftUI 創作圓點工作指示器
xcode 13.4.1, swift 5.5, iOS 15.4
2022-08-16
使用簡單的動畫就可以創作以下的圓點工作指示器。
1. 首先先創建一個綠色圓點。
import SwiftUI

struct DotLoadingExample : View {
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
    }
}
2. 然後使用scaleEffect來設置圓點的大小:
import SwiftUI

struct DotLoadingExample : View {
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
            .scaleEffect(0.5)
    }
}
3. 再來就是試試用animation來作圓點大小的動畫:
import SwiftUI

struct DotLoadingExample : View {
    @State var scaleEffect : CGFloat = 0.01
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
            .scaleEffect(scaleEffect)
            .animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
            .onAppear {
                scaleEffect = 1.0
            }

    }
}
4. 現在把小圓點包裝成一個元件,并同時放置兩個小圓點元件,看看效果。
import SwiftUI

struct DotAnimation : View {
    @State var scaleEffect : CGFloat = 0.01
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
            .scaleEffect(scaleEffect)
            .animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
            .onAppear {
                scaleEffect = 1.0
            }

    }
}
struct DotLoadingExample : View {
    var body: some View {
        HStack {
            DotAnimation()
            DotAnimation()
        }
    }
}
5. 上面看到兩個小圓點同時進行在作相同的變化,為了讓每個小圓點的變化有先後順序的感覺,在每個小圓點開始動畫之前設置一個延遲時間值,避免所有小圓點一起作相同的變化。
import SwiftUI

struct DotAnimation : View {
    let delay : Double
    @State var scaleEffect : CGFloat = 0.01
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
            .scaleEffect(scaleEffect)
            .animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                    scaleEffect = 1.0
                }
            }

    }
}
struct DotLoadingExample : View {
    var body: some View {
        HStack {
            DotAnimation(delay: 0.1)
            DotAnimation(delay: 0.2)
        }
    }
}
6. 最後把9個小圓點放在一起,每個小圓點相隔0.1秒才開始動畫,實作如下:
import SwiftUI

struct DotAnimation : View {
    let delay : Double
    @State var scaleEffect : CGFloat = 0.01
    var body: some View {
        Circle()
            .foregroundColor(.green)
            .frame(width: 20)
            .scaleEffect(scaleEffect)
            .animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                    scaleEffect = 1.0
                }
            }

    }
}
struct DotLoadingExample : View {
    var body: some View {
        HStack {
            ForEach(1...9, id:\.self) { index in
                DotAnimation1(delay: 0.1 * CGFloat(index))
            }
        }
    }
}