はじめに
この記事では、SwiftUIで美しいカラーボールアニメーションを作る方法を紹介します。
作るもの
7色のカラーボールがなめらかに動くアニメーションを作ります。
デモ
作り方
コード全体
import SwiftUI
struct AnimatedSevenGradientBallsView: View {
private let colors: [Color]
private let colorsCount: Int
@State private var positions: [CGPoint]
@State private var show = true
init() {
colors = [
.red,
.orange,
.yellow,
.green,
.blue,
.purple,
.pink
]
colorsCount = colors.count
positions = Array(repeating: .zero, count: colorsCount)
}
var body: some View {
ZStack {
if show {
ForEach(0..<colorsCount, id: \.self) { index in
Circle()
// Colorのgradientプロパティを使うと、
// その色のグラデーションを作れる
.fill(colors[index].gradient)
// blendModeをlightenにすると、
// 重なった部分が明るくなる
.blendMode(.lighten)
.frame(width: 160, height: 160)
.offset(x: positions[index].x, y: positions[index].y)
.animation(
// repeatForeverで繰り返しアニメーションを作れる
// autoreversesをtrueにすると、
// アニメーションが終わったら逆方向にアニメーションする
// delayでアニメーションの開始を遅らせることができる
// ここでは、indexに応じてアニメーションの開始を遅らせている
// そうすることで美しいアニメーションを実現している
.easeInOut(duration: 1).repeatForever(autoreverses: true).delay(Double(index) * 0.1),
value: positions
)
}
}
Rectangle()
// Materialを使うと、
// 背後に表示されるビューにぼかしをかけられる
.fill(Material.ultraThin)
.ignoresSafeArea()
}
.preferredColorScheme(.dark) // 常にダークモードにする
.onAppear {
setPositions()
}
// iPhoneを回転させるとアニメーションが止まるバグがあるので、
// リロードできるようにしている
.onTapGesture {
show.toggle()
}
.onChange(of: show) { show in
if show {
setPositions()
} else {
positions = Array(repeating: .zero, count: colorsCount)
}
}
}
private func setPositions() {
// 角円の座標を円状に配置する(最初は全て中心にある)
for index in 0 ..< colorsCount {
positions[index] = CGPoint(
x: 80 * cos(Double(index) * 2 * Double.pi / Double(colorsCount)),
y: 80 * sin(Double(index) * 2 * Double.pi / Double(colorsCount))
)
}
}
}
ポイント
- blendModeをlightenにすると、重なった部分が明るくなる
- repeatForeverで繰り返しアニメーションを作れる
- autoreversesをtrueにすると、アニメーションが終わったら逆方向にアニメーションできる
- 最初は全て中心にある角円の座標を円状に配置する(この時にアニメーションがかかる)
まとめ
SwiftUIで美しいカラーボールアニメーションを作りました。SwiftUIのテクニックが多く詰まっているので、自分でもまた見返したいと思いました👀