8 aout 2025 - Suite des Animations SwiftUI : quand l’interface prend vie
Voici ce que j’ai vu au niveau des animations ce vendredi. je poste cet article le dimanche car j’ai eu la flemme de le faire vendredi.
#
Apprentissages du jour : Les animations SwiftUI
##
Animation implicite : le modificateur .animation()
.animation()
La première approche que j’ai découverte, c’est l’animation implicite. SwiftUI surveille automatiquement les changements d’état et les anime :
struct ContentView: View {
@State private var enabled = false
var body: some View {
Button("Tap Me"){
enabled.toggle()
}
.frame(width: 200, height: 200)
.background(enabled ? .blue : .red)
.foregroundStyle(.white)
.animation(.default, value: enabled)
.clipShape(.rect(cornerRadius: enabled ? 60 : 0))
.animation(.spring(duration: 1, bounce: 0.6), value: enabled)
}
}
Astuce importante : On peut appliquer différentes animations à différentes propriétés du même élément !
##
Gestes et animations : le drag interactif
L’une des choses les plus impressionnantes que j’ai testées aujourd’hui, ce sont les gestes de drag combinés aux animations :
struct ContentView: View {
@State private var dragAmount = CGSize.zero // CGSize du framework CoreGraphics
var body: some View {
LinearGradient(colors: [.yellow, .red], startPoint: .topLeading, endPoint: .bottomTrailing)
.frame(width: 300, height: 200)
.clipShape(.rect(cornerRadius: 10))
.offset(dragAmount)
.gesture(
DragGesture()
.onChanged { dragAmount = $0.translation }
.onEnded { _ in
withAnimation(.bouncy) {
dragAmount = .zero
}
}
)
}
}
##
Animation séquentielle : l’effet lettres
L’un des exemples les plus spectaculaires que j’ai réalisé aujourd’hui, c’est l’animation de lettres individuelles :
struct ContentView: View {
let letters = Array("Hello SwiftUI")
@State private var enabled = false
@State private var dragAmount = CGSize.zero
var body: some View {
HStack (spacing: 0){
ForEach(0..<letters.count, id: \.self) { num in
Text(String(letters[num]))
.padding(5)
.font(.title)
.background(enabled ? .blue : .red)
.offset(dragAmount)
.animation(.linear.delay(Double(num) / 20), value: dragAmount)
}
}
.gesture(
DragGesture()
.onChanged { dragAmount = $0.translation }
.onEnded { _ in
dragAmount = .zero
enabled.toggle()
}
)
}
}
Chaque lettre s’anime avec un délai différent, créant un effet de vague.
##
Transitions : apparition et disparition
Les transitions permettent de contrôler comment les éléments apparaissent et disparaissent :
struct ContentView: View {
@State private var isShowingRed = false
var body: some View {
VStack {
Button("Tap Me") {
withAnimation {
isShowingRed.toggle()
}
}
if isShowingRed {
Rectangle()
.fill(.red)
.frame(width: 200, height: 200)
.transition(.asymmetric(insertion: .push(from: .bottom), removal: .push(from: .top)))
}
}
}
}
L’approche asymétrique permet d’avoir des animations différentes à l’entrée et à la sortie.
##
ViewModifier personnalisé : créer ses propres transitions
Le concept le plus avancé que j’ai découvert aujourd’hui, c’est la création de transitions personnalisées avec des ViewModifiers :
struct CornerRotateModifier: ViewModifier {
let amount: Double
let anchor: UnitPoint
func body(content: Content) -> some View {
content
.rotationEffect(.degrees(amount), anchor: anchor)
.clipped()
}
}
extension AnyTransition {
static var pivot: AnyTransition {
.modifier(
active: CornerRotateModifier(amount: -90, anchor: .topLeading),
identity: CornerRotateModifier(amount: 0, anchor: .topLeading))
}
}
Cette approche permet de créer des effets uniques personnalisés pour tes applications !
#
Ma création personnelle : l’animation “WRONG!”
Je suis assez fier de cette petite animation que j’ai créée pour tester mes connaissances :
struct ContentView: View {
@State private var isWrong = true
var body: some View {
ZStack {
Capsule()
.frame(width: 100, height: 30)
Text("WRONG !")
.foregroundStyle(.white)
}
.offset(x: isWrong ? 10: 0)
.onTapGesture {
isWrong = false
withAnimation(.bouncy(duration: 0.2, extraBounce: 0.6).repeatCount(1)){
isWrong = true
}
}
}
}
L’idée : quand on tape sur le bouton, le bouton vibre pour indiquer une erreur. L’animation .bouncy
avec extraBounce
donne vraiment l’impression d’un objet qui vibre de frustration !
Alessandro