Skip to content

Instantly share code, notes, and snippets.

@truizlop
Created September 29, 2020 15:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save truizlop/6642625a409dd0ab85ab2f1e179cbcac to your computer and use it in GitHub Desktop.
Save truizlop/6642625a409dd0ab85ab2f1e179cbcac to your computer and use it in GitHub Desktop.
Circle wave animation
import SwiftUI
struct CircleWave: Shape {
let N = 360
let SPEED: Double = 1 / 1000.0
let SHIFT: Double = 2 * Double.pi / 3
let FREQUENCY: Double = 8
var factor: Double
var colorIndex: Double
var animatableData: Double {
get { factor }
set { self.factor = newValue }
}
func path(in rect: CGRect) -> Path {
Path { path in
let waveAmplitude: Double = Double(rect.size.minDimension) / 20
let circleRadius: Double = Double(rect.size.minDimension) / 2 - 2 * waveAmplitude
(0 ..< N).forEach { i in
let a: Double = Double(i) * 2 * Double.pi / Double(N)
let t: Double = factor * SPEED
let c: Double = cos(a * FREQUENCY - colorIndex * SHIFT + t)
let p: Double = pow(((1 + cos(a - t)) / 2), 3)
let r: Double = Double(circleRadius + waveAmplitude * c * p)
let x: Double = r * sin(a)
let y: Double = r * -cos(a)
if i == 0 {
path.move(to: CGPoint(x: x, y: y))
} else {
path.addLine(to: CGPoint(x: x, y: y))
}
}
path.closeSubpath()
}
}
}
struct AnimatedCircleWave: View {
@State var factor: Double = 0
@State var rotation: Double = 0
var body: some View {
GeometryReader { proxy in
ZStack {
CircleWave(factor: factor, colorIndex: 0)
.stroke(Color.magenta, lineWidth: 8)
.blendMode(.darken)
CircleWave(factor: factor, colorIndex: 1)
.stroke(Color.cyan, lineWidth: 8)
.blendMode(.darken)
CircleWave(factor: factor, colorIndex: 2)
.stroke(Color.yellow, lineWidth: 8)
.blendMode(.darken)
}.transformEffect(translate(to: proxy.size))
}.onAppear {
withAnimation(self.animation) {
self.factor = 2 * Double.pi * 1000
}
}
}
var animation: Animation {
Animation.linear(duration: 3).repeatForever(autoreverses: false)
}
func translate(to size: CGSize) -> CGAffineTransform {
CGAffineTransform(
translationX: size.width / 2,
y: size.height / 2)
}
}
extension Color {
static var magenta: Color {
Color(red: 1, green: 0, blue: 1)
}
static var cyan: Color {
Color(red: 0, green: 1, blue: 1)
}
}
extension CGSize {
var minDimension: CGFloat {
min(width, height)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment