Skip to content

Instantly share code, notes, and snippets.

@dduan
Last active June 20, 2020 13:56
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dduan/ea3bf501d548e6b194dd7f637bf3ba54 to your computer and use it in GitHub Desktop.
Save dduan/ea3bf501d548e6b194dd7f637bf3ba54 to your computer and use it in GitHub Desktop.
Twitter's voice tweet UI has an interesting animation on iOS. This is an attempt to recreate that animation with SwiftUI. Looks like this https://youtu.be/I6XZzIgWYAQ
import SwiftUI
struct ChaoticPhoto: View {
let image: Image
let radius: CGFloat
@Binding var activated: Bool
@State var scale: CGFloat = 1
var body: some View {
image
.resizable()
.frame(width: radius, height: radius)
.mask(Circle())
.scaleEffect(activated ? scale : 1)
.onAppear {
Timer.scheduledTimer(
withTimeInterval: 0.05,
repeats: true
) { _ in
self.scale = CGFloat.random(in: 1...1.1)
}
}
}
}
struct ChaoticCircle: View {
let radius: CGFloat
@Binding var activated: Bool
@State var scale: CGFloat = 1
@State var offSet: CGFloat = 0
@State var xDirection: CGFloat = 0
@State var yDirection: CGFloat = 0
var body: some View {
Circle()
.fill(Color.white.opacity(0.15))
.frame(width: radius, height: radius)
.offset(
x: activated ? xDirection * offSet : 0,
y: activated ? yDirection * offSet : 0
)
.scaleEffect(activated ? scale : 1)
.onAppear(perform: {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
withAnimation(Animation.easeInOut(duration: 0.1)) {
self.xDirection = [CGFloat(0.0), CGFloat(1), CGFloat(-1)].randomElement() ?? CGFloat(0)
self.yDirection = [CGFloat(0.0), CGFloat(1), CGFloat(-1)].randomElement() ?? CGFloat(0)
self.offSet = CGFloat.random(in: 5...8)
self.scale = CGFloat.random(in: CGFloat(1.2)...CGFloat(1.4))
}
}
})
}
}
struct ActivateButton: View {
@Binding var activated: Bool
var body: some View {
Button(action: {
self.activated.toggle()
}) {
Text(activated ? "Stop" : "Speak")
.frame(width: 200, height: 44)
.foregroundColor(Color.white)
.background(
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color("main"))
)
}
.shadow(color: Color.white, radius: 5)
}
}
struct ContentView: View {
@State var activated = false
var body: some View {
VStack {
Spacer()
ZStack {
ChaoticCircle(radius: 100, activated: self.$activated)
ChaoticCircle(radius: 100, activated: self.$activated)
ChaoticCircle(radius: 100, activated: self.$activated)
ChaoticPhoto(image: Image("profile photo"), radius: 98, activated: self.$activated)
}
Spacer()
ActivateButton(activated: $activated)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color("main").saturation(0.6))
.edgesIgnoringSafeArea(.all)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment