import SwiftUI
func deg2rad(_ number: Double) -> Double {
return number * Double.pi / 180
}
struct Spark: Hashable {
var size: CGFloat = 15
var x: CGFloat = 0
var y: CGFloat = 0
var x2: CGFloat = 0
var y2: CGFloat = 0
var duration: Double = 1.5
var delay: Double = 1.2
var color: Double
}
struct TwitterLike: View {
@State private var touch: Bool = false
@State private var start: Bool = false
@State private var finish: Bool = false
private var base: Animation = Animation.timingCurve(0.54, 1.65, 0.68, 0.79, duration: 0.5)
private var positions: [Spark] {
var arr: [Spark] = []
let shortDistance: Double = 90
let longDistance: Double = 110
for i in 0...6 {
let angle = (Double(i) * 51) - 8
let rad = deg2rad(angle)
arr.append(Spark(
size: 20,
x: CGFloat(longDistance * cos(rad)),
y: CGFloat(longDistance * sin(rad)),
x2: CGFloat((longDistance + 10) * cos(rad)),
y2: CGFloat((longDistance + 10) * sin(rad)),
delay: 1.2,
color: angle
))
let angle2 = (Double(i) * 51) - 20;
let rad2 = deg2rad(angle2)
arr.append(Spark(
size: 7,
x: CGFloat(shortDistance * cos(rad2)),
y: CGFloat(shortDistance * sin(rad2)),
x2: CGFloat((shortDistance + 10) * cos(rad2)),
y2: CGFloat((shortDistance + 10) * sin(rad2)),
duration: 1.2,
color: angle2
))
}
return arr
}
var body: some View {
ZStack {
ZStack {
sparks
if !self.finish {
Circle()
.scale(x: touch ? 1 : 0, y: touch ? 1 : 0, anchor: .center)
.foregroundColor(Color(UIColor.systemIndigo))
.clipShape(
Circle().stroke(lineWidth: 120)
)
.animation(base.delay(0.3))
.clipShape(
Circle().stroke(lineWidth: touch ? 0 : 120)
)
.animation(Animation.easeInOut(duration: touch ? 0.5 : 0).delay(0.5))
.frame(width: 120, height: 120)
}
ZStack {
Image(systemName: "heart.fill")
.resizable()
.scaleEffect(touch ? 0 : 1)
.aspectRatio(contentMode: .fit)
.opacity(touch ? 0 : 0.4)
.foregroundColor(Color(UIColor.systemGray))
.animation(base)
Image("HeartBG")
.resizable()
.scaleEffect(touch ? 1 : 0)
.aspectRatio(contentMode: .fit)
.opacity(touch ? 1 : 0)
.mask(
Image(systemName: "heart.fill")
.resizable()
.scaleEffect(touch ? 1 : 0)
.aspectRatio(contentMode: .fit)
)
.animation(Animation.timingCurve(0.17,1.67,0.61,0.77, duration: touch ? 0.8 : 0).delay(touch ? 0.8 : 0))
Image(systemName: "heart.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.opacity(touch ? 1 : 0)
.foregroundColor(Color(UIColor.systemRed))
.animation(Animation.timingCurve(0.54, 1.65, 0.68, 0.79, duration: touch ? 1 : 0).delay(touch ? 2.5 : 0))
}.frame(width: 80)
}.frame(width: 80)
}
.frame(width: 80)
.onTapGesture{
if self.start {
return
}
self.touch.toggle()
if self.touch {
self.start = true
self.finish = false
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.start = false
self.finish = true
}
} else {
self.finish = false
}
}
}
private var sparks: some View {
ZStack {
ForEach(positions, id: \.self) { pos in
Circle()
.scaleEffect(x: touch ? 1 : 0.5, y: touch ? 1 : 0.5, anchor: .center)
.foregroundColor(Color(UIColor.systemIndigo))
.hueRotation(Angle(degrees: touch ? pos.color + 360 : 0))
.opacity(touch ? 1 : 0)
.offset(x: touch ? pos.x : 0, y: touch ? pos.y : 0)
.frame(width: pos.size, height: pos.size)
.animation(Animation.timingCurve(0.5, 1, 0.89, 1, duration: touch ? pos.duration : 0).delay(touch ? 0.3 : 0))
.opacity(touch ? 0.4 : 1)
.hueRotation(Angle(degrees: touch ? pos.color + 360 : 0))
.animation(Animation.timingCurve(0.5, 1, 0.89, 1, duration: touch ? 1 : 0).delay(touch ? 1.5 : 0))
.scaleEffect(x: touch ? 0 : 1, y: touch ? 0 : 1, anchor: .center)
.offset(x: touch ? pos.x2 : 0, y: touch ? pos.y2 : 0)
.animation(Animation.timingCurve(0.5, 1, 0.89, 1, duration: touch ? 1.8 : 0).delay(touch ? pos.delay : 0))
}
}.frame(width: 20, height: 20)
}
}
Twitter Like animation in SwiftUI
by Kane
For some time now Twitter has been using nice-looking animation that is shown when user clicks on a Like (heart) icon.
Icon goes through some transformations with circle from which heart appears and dozen of sparks start flying outside.
Original Twitter animation was done in After Effects according to @wongmjane.
In this component you can find approximation of that Like animation done with only SwiftUI, default iOS colors and some creative use of masks and clip shapes.
Icon goes through some transformations with circle from which heart appears and dozen of sparks start flying outside.
Original Twitter animation was done in After Effects according to @wongmjane.
In this component you can find approximation of that Like animation done with only SwiftUI, default iOS colors and some creative use of masks and clip shapes.