Created
September 29, 2020 15:43
-
-
Save truizlop/6642625a409dd0ab85ab2f1e179cbcac to your computer and use it in GitHub Desktop.
Circle wave animation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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