Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@aheze
Created October 3, 2022 02:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aheze/c720f8e0393a06cb3e48ef7425960bfd to your computer and use it in GitHub Desktop.
Save aheze/c720f8e0393a06cb3e48ef7425960bfd to your computer and use it in GitHub Desktop.
SwiftUI pulse animation
struct ContentView: View {
static let fadeInDuration = CGFloat(1.1)
static let pulseDuration = CGFloat(1.6)
static let fadeOutDuration = CGFloat(0.3)
static let interval = CGFloat(1.6)
@State var isAnimating = false
@State var timer = Timer.publish(every: interval, on: .main, in: .common).autoconnect()
@State var circlesIDs = [UUID()]
var body: some View {
Color.gray.overlay {
ZStack {
ForEach(circlesIDs, id: \.self) { _ in
circle
}
}
}
.onReceive(timer) { _ in
if isAnimating {
circlesIDs.append(UUID())
circlesIDs.removeFirst()
}
}
.onTapGesture {
isAnimating.toggle()
}
}
var circle: some View {
Circle()
.frame(width: 30)
.foregroundColor(.yellow)
.transition(
.asymmetric(
insertion: .pulse /// Special transition that starts out with 1 opacity and goes to 0.
.animation(
.easeInOut(duration: Self.pulseDuration)
)
.combined(with: /// Add the fade in transition.
.opacity
.animation(
.linear(duration: Self.fadeInDuration)
)
),
removal: .opacity /// For removal, a simple opacity fade is fine.
.animation(
.easeInOut(duration: Self.fadeOutDuration)
)
)
)
}
}
extension AnyTransition {
static var pulse: AnyTransition {
.modifier(
active: PulseModifier(transitioning: true),
identity: PulseModifier(transitioning: false)
)
}
}
struct PulseModifier: ViewModifier {
var transitioning: Bool
func body(content: Content) -> some View {
content
.opacity(transitioning ? 1 : 0)
.scaleEffect(transitioning ? 0.45 : 2)
}
}
@aheze
Copy link
Author

aheze commented Oct 3, 2022

Result:

PulseAnimation.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment