- Published on
SwiftUI'da shaxsiy shakllarni animatsiya qilish (AnimatableData)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Oddiy o'zgaruvchilar bilan muammo
Avvalgi darslarda biz o'zimizning shaxsiy (Custom) shakllarimizni yasashni o'rgandik. Aytaylik, biz faqatgina bitta burchagi yoy (rounded) bo'ladigan Maxsus To'rtburchak chizdik. Uni chizishda bizga burchak qanchalik bukilishini bildirish uchun parametr kerak bo'ladi (var cornerRadius: CGFloat).
Agar biz bu parametrni vaqt o'tishi bilan o'zgartirsak (masalan tugma bosilganda 0 dan 60 ga o'zgartirsak) qiziq xolat yuz beradi: shakl o'zgaradi, lekin Silliq Animatsiya bilan emas! U birdaniga "sakrab" o'zgaradi. withAnimation ga o'rab qo'ygan bo'lsak ham animatsiya ishlamaydi! Nima uchun?
Sababi oddiy: SwiftUI dagi tayyor Rectangle ichida barcha narsa Apple tomonidan animatsiya qilishga sozlangan. Lekin biz yaratgan Custom Shape da path() funksiyasi qaysi raqam aynan animatsiya bilan o'zgarishi kerakligini bilmaydi.
AnimatableData nima?
Ushbu muammoni hal qilishning yagona yo'li — SwiftUI ga qaysi malumot "jonli" (animatable) ekanligini ochiq aytishdir. Buning uchun animatableData nomli maxsus parametrni yozishimiz shart.
1-Misol: Faqat bir burchagi aylanadigan to'rtburchak
import SwiftUI
struct RectangleWithSingleCornerAnimation: Shape {
var cornerRadius: CGFloat
// SIRLI KALIT SHU YERDA:
var animatableData: CGFloat {
get { cornerRadius }
set { cornerRadius = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
// Tepadan o'ngga
path.move(to: .zero)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
// O'ng tepadan O'ng pastga (burchakkacha etib bormaymiz, burilish uchun joy qoldiramiz)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - cornerRadius))
// Burchakda yoy chizamiz (Burilish)
path.addArc(
center: CGPoint(x: rect.maxX - cornerRadius, y: rect.maxY - cornerRadius),
radius: cornerRadius,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: 90),
clockwise: false
)
// Pastdan chapga
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
// Va yana boshlagan nuqtaga
path.addLine(to: .zero)
return path
}
}
Endi, biz qachonki cornerRadius ni o'zgartirsak, SwiftUI uning get va set metodlariga o'tib, eski va yangi raqamlar orasidagi 1,2,3,4 kabi oraliq raqamlarni birma-bir o'zgartirib ajoyib silliq animatsiyani vujudga keltiradi!
2-Misol: animatsiyali Pac-Man
Bu narsa faqat radiuslarga emas, balki graduslarga (degrees) ham ishlaydi. Keling og'zini ochib-yopadigan Pac-Man yasaymiz.
struct Pacman: Shape {
var offsetAmount: Double // Og'izning qanchalik ochilishi (gradusda)
// BUNI YOZMASAK OG'IZ OCHILIB YOPILISHI SAKRAB ISHLAYDI!
var animatableData: Double {
get { offsetAmount }
set { offsetAmount = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
// O'rtadan boshlaymiz
path.move(to: CGPoint(x: rect.midX, y: rect.midY))
// Yoy qo'shamiz (OffsetAmount qancha katta bo'lsa, og'iz shuncha ko'p ochiladi)
path.addArc(
center: CGPoint(x: rect.midX, y: rect.midY),
radius: rect.height / 2,
startAngle: Angle(degrees: offsetAmount),
endAngle: Angle(degrees: 360 - offsetAmount),
clockwise: false
)
return path
}
}
Bu shaklni oynaga qo'shganimizda uni withAnimation bilan ochib yopish qanchalik qulay va tayyorligini ko'rasiz:
struct AnimatableDataBootcamp: View {
@State private var animate: Bool = false
var body: some View {
ZStack {
Pacman(offsetAmount: animate ? 20 : 0)
.fill(Color.yellow)
.frame(width: 200, height: 200)
.onAppear {
// Tinimsiz takrorlanuvchi animatsiya ulaymiz
withAnimation(Animation.easeInOut.repeatForever()) {
animate.toggle()
}
}
}
}
}
Xulosa shuki: Agar Custom Shape yozsangiz va u nimagadir animatsiya bilan silliq o'zgarmayotgan bo'lsa, siz albatta animatableData yozishni esdan chiqargansiz!