はじめに
ローディング画面をカスタムして作ってみました
完成形
実装
import SwiftUI
struct CircularLoadingIndicator: View {
@State private var scale: CGFloat = 0.25
private let numberOfCircles = 12
private let circleSize: CGFloat = 10
private let animationDuration: Double = 0.8
var body: some View {
GeometryReader { geometry in
ZStack {
ForEach(0..<numberOfCircles, id: \.self) { index in
circleView(index: index)
.frame(width: circleSize, height: circleSize)
.position(circlePosition(for: index, in: geometry.size))
}
}
}
}
private func circleView(index: Int) -> some View {
Circle()
.scaleEffect(scale)
.animation(
.easeInOut(duration: animationDuration)
.repeatForever(autoreverses: true)
.delay(Double(index) * (animationDuration / Double(numberOfCircles))),
value: scale
)
.onAppear { scale = 1.0 }
}
private func circlePosition(for index: Int, in size: CGSize) -> CGPoint {
let center = CGPoint(x: size.width / 2, y: size.height / 2)
let radius = min(size.width, size.height) / 3
let angle = 2 * .pi / Double(numberOfCircles) * Double(index)
let x = center.x + CGFloat(cos(angle)) * radius
let y = center.y + CGFloat(sin(angle)) * radius
return CGPoint(x: x, y: y)
}
}
使い方
CircularLoadingIndicator()
.foregroundColor(.orange)
.frame(width: 80, height: 80)
.contentShape(RoundedRectangle(cornerRadius: 10))
.frame(width: 140, height: 140)
.background(RoundedRectangle(cornerRadius: 10).fill(Material.thick))
おわり
アニメーション職人になりたい