Skip to content

Instantly share code, notes, and snippets.

@Dev1an
Last active May 14, 2021 08:07
Show Gist options
  • Save Dev1an/710fcb0a7a2d75f2d595fb29ca07a5b4 to your computer and use it in GitHub Desktop.
Save Dev1an/710fcb0a7a2d75f2d595fb29ca07a5b4 to your computer and use it in GitHub Desktop.
Add a jump animation whenever a value changes in SwiftUI
//
// ContentView.swift
// badger
//
// Created by Damiaan on 12/05/2021.
//
import SwiftUI
struct Badge: View {
let count: Int
var body: some View {
Text("\(count)")
.foregroundColor(.white)
.jumpOnChange(of: count)
.animation(.easeOut(duration: 0.6))
.padding(.horizontal, 8)
.padding(.vertical, 2)
.background(
Capsule()
.foregroundColor(.accentColor)
.animation(.spring()) // Animate the width of the capsule
)
}
}
struct ContentView: View {
@State var count = 23
var body: some View {
VStack {
Badge(count: count)
HStack {
Button("+") { count += 1 }
Button("-") { count -= 1 }
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
//
// Jumper.swift
//
// Created by Damiaan on 13/05/2021.
//
import SwiftUI
extension View {
func jumpOnChange<Data: Equatable>(of value: Data) -> some View {
modifier(Jumper(value: value))
}
}
struct Jumper<Data: Equatable>: ViewModifier {
@State private var position: CGFloat = 0
let value: Data
func body(content: Content) -> some View {
content
.animation(nil)
.modifier(Displacement(animatableData: position))
.onChange(of: value) { _ in toggle() }
}
func toggle() {
if position == .zero {
position = 3 * .pi
} else {
position = 0
}
}
struct Displacement: GeometryEffect {
var animatableData: CGFloat
func effectValue(size: CGSize) -> ProjectionTransform {
.init(
CGAffineTransform(
translationX: 0,
y: 3 * sin(animatableData)
)
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment