- Published on
Custom Shape, Path va Animatable
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
SwiftUI da tayyor shakllar bor — Circle, Rectangle, Capsule. Lekin real ilovalarda maxsus shakllar kerak. Path va Shape bilan istalgan shakl yaratish mumkin.
Path asoslari
// ═══════════════════════════════════════
// PATH — qo'lda shakl chizish
// ═══════════════════════════════════════
struct UchburchakPath: View {
var body: some View {
Path { path in
// Boshlang'ich nuqta
path.move(to: CGPoint(x: 100, y: 0))
// Chiziqlar
path.addLine(to: CGPoint(x: 200, y: 150))
path.addLine(to: CGPoint(x: 0, y: 150))
// Yopish
path.closeSubpath()
}
.fill(.blue.gradient)
}
}
Shape protokoli
// ═══════════════════════════════════════
// CUSTOM SHAPE — o'z shaklingiz
// ═══════════════════════════════════════
struct Yulduz: Shape {
let qirralariSoni: Int
let ichkiRadius: CGFloat // Ichki radius nisbati (0...1)
// path(in:) — shaklni chizish
func path(in rect: CGRect) -> Path {
let markaz = CGPoint(x: rect.midX, y: rect.midY)
let tashqiRadius = min(rect.width, rect.height) / 2
let ichki = tashqiRadius * ichkiRadius
var path = Path()
let nuqtalar = qirralariSoni * 2
for i in 0..<nuqtalar {
let burchak = Double(i) * .pi / Double(qirralariSoni) - .pi / 2
let radius = i.isMultiple(of: 2) ? tashqiRadius : ichki
let nuqta = CGPoint(
x: markaz.x + CGFloat(cos(burchak)) * radius,
y: markaz.y + CGFloat(sin(burchak)) * radius
)
if i == 0 {
path.move(to: nuqta)
} else {
path.addLine(to: nuqta)
}
}
path.closeSubpath()
return path
}
}
// Ishlatish
Yulduz(qirralariSoni: 5, ichkiRadius: 0.4)
.fill(.yellow.gradient)
.frame(width: 100, height: 100)
.trim() bilan animatsiya
// ═══════════════════════════════════════
// TRIM — chizilish animatsiyasi
// ═══════════════════════════════════════
struct ChizilishAnimatsiyasi: View {
@State private var foiz: CGFloat = 0
var body: some View {
ZStack {
// Fon doira
Circle()
.stroke(.gray.opacity(0.2), lineWidth: 8)
// Animatsiyali doira
Circle()
.trim(from: 0, to: foiz)
.stroke(
.blue.gradient,
style: StrokeStyle(
lineWidth: 8,
lineCap: .round
)
)
.rotationEffect(.degrees(-90))
// Foiz matni
Text("\(Int(foiz * 100))%")
.font(.title.bold())
}
.frame(width: 120, height: 120)
.onAppear {
withAnimation(.easeOut(duration: 1.5)) {
foiz = 0.75
}
}
}
}
Animatable Shape
// ═══════════════════════════════════════
// ANIMATABLE — shape parametrini animatsiya qilish
// ═══════════════════════════════════════
struct TolqinShakl: Shape {
var foiz: CGFloat // Animatsiya qilinadigan qiymat
// animatableData — SwiftUI bu qiymatni interpolyatsiya qiladi
var animatableData: CGFloat {
get { foiz }
set { foiz = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
let kenglik = rect.width
let balandlik = rect.height
path.move(to: CGPoint(x: 0, y: balandlik * foiz))
// To'lqin chizish
for x in stride(from: 0, through: kenglik, by: 1) {
let nisbiy = x / kenglik
let y = balandlik * foiz + sin(nisbiy * .pi * 4) * 10
path.addLine(to: CGPoint(x: x, y: y))
}
path.addLine(to: CGPoint(x: kenglik, y: balandlik))
path.addLine(to: CGPoint(x: 0, y: balandlik))
path.closeSubpath()
return path
}
}
struct TolqinKorinishi: View {
@State private var foiz: CGFloat = 0.6
var body: some View {
TolqinShakl(foiz: foiz)
.fill(.blue.gradient.opacity(0.5))
.frame(height: 200)
.onAppear {
withAnimation(.easeInOut(duration: 2).repeatForever()) {
foiz = 0.3
}
}
}
}
🎯 Topshiriq
5 qirrali yulduz Shape yarating, .trim() bilan chizilish animatsiyasi qo'shing. Keyin Animatable protokolini qo'llab, yulduz qirralarining ichki radiusini animatsiya qiling (yulduzdan doiraga o'tish effekti).