Last active
March 7, 2025 13:53
-
-
Save TAATHub/a34152d8563a54c2a9027fc0c05bb2af to your computer and use it in GitHub Desktop.
aaaaaa
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 AnimatedLikeView: View { | |
@State private var isFavorite = false | |
var body: some View { | |
VStack(spacing: 60) { | |
Button { | |
withAnimation(.none) { | |
isFavorite.toggle() | |
} | |
} label: { | |
if isFavorite { | |
Image(systemName: "heart.fill") | |
.foregroundStyle(.blue) | |
.transition(.confetti(color: .blue, size: 5)) | |
} else { | |
Image(systemName: "heart") | |
.foregroundStyle(.gray) | |
} | |
} | |
.font(.system(size: 128)) | |
} | |
} | |
} | |
#Preview { | |
AnimatedLikeView() | |
} |
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 ConfettiModifier: ViewModifier { | |
@State private var circleSize = 0.00001 | |
@State private var strokeMultipler: CGFloat = 1.0 | |
@State private var confettiIsHidden = true | |
@State private var confettiMovement = 0.7 | |
@State private var confettiScale = 1.0 | |
@State private var contentsScale = 0.00001 | |
private let speed = 0.3 | |
var color: Color | |
var size: Double | |
func body(content: Content) -> some View { | |
content | |
.hidden() | |
.padding(10) | |
.overlay( | |
ZStack { | |
GeometryReader { proxy in | |
Circle() | |
.strokeBorder(color, lineWidth: proxy.size.width / 2 * strokeMultipler) | |
.scaleEffect(circleSize) | |
ForEach(0..<15) { i in | |
Circle() | |
.fill(color) | |
.frame(width: size + sin(Double(i)), height: size + sin(Double(i))) | |
.scaleEffect(confettiScale) | |
.offset(x: proxy.size.width / 2 * confettiMovement + (i.isMultiple(of: 2) ? size : 0)) | |
.rotationEffect(.degrees(24 * Double(i))) | |
.offset(x: (proxy.size.width - size) / 2, y: (proxy.size.height - size) / 2) | |
.opacity(confettiIsHidden ? 0 : 1) | |
} | |
} | |
content | |
.scaleEffect(contentsScale) | |
} | |
) | |
.padding(-10) | |
.onAppear { | |
withAnimation(.easeIn(duration: speed)) { | |
circleSize = 1 | |
} | |
withAnimation(.easeOut(duration: speed).delay(speed)) { | |
strokeMultipler = 0.00001 | |
} | |
withAnimation(.easeOut(duration: speed).delay(speed * 1.25)) { | |
confettiIsHidden = false | |
confettiMovement = 1.2 | |
} | |
withAnimation(.easeOut(duration: speed).delay(speed * 2)) { | |
confettiScale = 0.00001 | |
} | |
withAnimation(.interpolatingSpring(stiffness: 50, damping: 5).delay(speed)) { | |
contentsScale = 1 | |
} | |
} | |
} | |
} | |
extension AnyTransition { | |
static var confetti: AnyTransition { | |
.modifier( | |
active: ConfettiModifier(color: .blue, size: 3), | |
identity: ConfettiModifier(color: .blue, size: 3) | |
) | |
} | |
static func confetti(color: Color = .blue, size: Double = 3.0) -> AnyTransition { | |
AnyTransition.modifier( | |
active: ConfettiModifier(color: color, size: size), | |
identity: ConfettiModifier(color: color, size: size) | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment