- Published on
SwiftUI crypto app — SwiftUI Shape yordamida chiziqli grafik yaratish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
SwiftUI crypto app — SwiftUI Shape yordamida chiziqli grafik yaratish
Bu dars butun kursning eng qiyin darslaridan biri. Matematik hisoblar bor, lekin men barchasi qadamma-qadam tushuntiraman. Biz so'nggi 7 kun narxlari uchun chiroyli chiziqli grafik yaratamiz — va uning rangi narx o'sgan bo'lsa yashil, tushgan bo'lsa qizil bo'ladi.
1. Sparkline ma'lumotlari
CoinModel-da sparklineIn7D.price — 168 ta raqamdan iborat array (7 kun × 24 soat). Bu — grafigimizdagi y-koordinata manbalari.
// coin.sparklineIn7D?.price -> [Double]
// Masalan: [54000, 53800, 55200, ...]
2. ChartView yaratish
core/detail/views papkasida ChartView.swift:
struct ChartView: View {
private let data: [Double]
private let maxY: Double
private let minY: Double
private let lineColor: Color
private let startingDate: Date
private let endingDate: Date
init(coin: CoinModel) {
data = coin.sparklineIn7D?.price ?? []
maxY = data.max() ?? 0
minY = data.min() ?? 0
// Narx oshganmi yoki tushganmi?
let priceChange = (data.last ?? 0) - (data.first ?? 0)
lineColor = priceChange > 0 ? Color.theme.green : Color.theme.red
endingDate = Date(coinGeckoString: coin.lastUpdated ?? "")
startingDate = endingDate.addingTimeInterval(-7 * 24 * 60 * 60) // 7 kun orqaga
}
var body: some View {
VStack {
chartView
.frame(height: 200)
.background(chartBackground)
.overlay(chartYAxis, alignment: .leading)
// Pastki sana belgilari
chartDateLabels
.padding(.horizontal, 4)
}
.font(.caption)
.foregroundColor(Color.theme.secondaryText)
}
}
3. Path va GeometryReader — grafikni chizish
Grafik koordinata tizimi tushuntirilishi:
iPhone ekranida (0, 0) nuqta yuqori chap burchak. Y qiymati pastga tomon oshadi. Shu sababli matematik formulada teskari yo'nalish kerak.
private var chartView: some View {
GeometryReader { geometry in
// Y-o'q diapazoni
let yAxis = maxY - minY
Path { path in
for index in data.indices {
// X koordinata: ekran kengligi / ma'lumotlar soni × indeks
let xPosition = geometry.size.width / CGFloat(data.count) * CGFloat(index + 1)
// Y koordinata hisoblash:
// 1. Ma'lumot nuqtasining minimumdan farqi
// 2. Y o'qiga nisbatan ulushi (foiz)
// 3. Grafikning haqiqiy balandligiga ko'paytirish
// 4. 1 - ni ayirish (iPhone koordinatasi teskari)
let yPosition = (1 - CGFloat((data[index] - minY) / yAxis)) * geometry.size.height
if index == 0 {
path.move(to: CGPoint(x: xPosition, y: yPosition))
}
path.addLine(to: CGPoint(x: xPosition, y: yPosition))
}
}
.stroke(
lineColor,
style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round)
)
}
}
Matematik misol: Bitcoin maksimali 60,000. Y-o'q = 10,000. Qiymat 52,000$ bo'lsa:
- Minimumdan farq: 52,000 - 50,000 = 2,000
- Foiz: 2,000 / 10,000 = 0.2 (20%)
- Teskari: 1 - 0.2 = 0.8 (80% pastdan, ya'ni yuqoridan 20%)
- Balandligi 200px bo'lsa: 0.8 × 200 = 160px (tepadan)
4. Fon grid chiziqlari
Grafikni "professional" ko'rinishga keltirish uchun orqa fonda uch qatorda gorizontal chiziqlar:
private var chartBackground: some View {
VStack {
Divider()
Spacer()
Divider()
Spacer()
Divider()
}
}
5. Y-o'q belgilari (eng yuqori, o'rta, eng past narx)
private var chartYAxis: some View {
VStack {
Text(maxY.formattedWithAbbreviations()) // Masalan: $58K
Spacer()
Text(((maxY + minY) / 2).formattedWithAbbreviations()) // O'rta narx
Spacer()
Text(minY.formattedWithAbbreviations()) // Masalan: $52K
}
}
6. Pastki sana belgilari
private var chartDateLabels: some View {
HStack {
Text(startingDate.asShortDateString()) // "Dec 3"
Spacer()
Text(endingDate.asShortDateString()) // "Dec 10"
}
}
Date+Extensions.swift-da:
// CoinGecko formatidan Date ga aylantirish
init(coinGeckoString: String) {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = formatter.date(from: coinGeckoString) ?? Date()
self.init(timeInterval: 0, since: date)
}
// Qisqa ko'rinish
func asShortDateString() -> String {
return self.formatted(.dateTime.month().day().year())
}
7. DetailView-ga ChartView qo'shish
DetailView-dagi bo'sh Text("") o'rniga:
var body: some View {
ScrollView {
VStack {
// Grafik — yuqori bo'lim
ChartView(coin: vm.coin)
.padding(.vertical)
VStack(spacing: 20) {
// ... statistika va tavsif
}
.padding()
}
}
}
8. Animatsiya qo'shish
Grafik ekranda paydo bo'lganda chizilish animatsiyasini qo'shish:
// ChartView ichida:
@State private var percentage: CGFloat = 0
// Path stroke-ni trim bilan:
.trim(from: 0, to: percentage)
// onAppear-da:
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
withAnimation(.linear(duration: 2.0)) {
percentage = 1.0
}
}
}
trim(from:to:)— path-ning qancha qismini ko'rsatishni belgilaydi. 0 dan 1 gacha animatsiya qilsak — grafik chap tomondancha o'ngga chiziladi.
Natija
Bitcoin detail ekraniga o'tsangiz:
- Agar 7 kun ichida narx oshgan bo'lsa — yashil chiziq
- Agar tushgan bo'lsa — qizil chiziq
- Yuqorida, o'rtada, pastda narx belgilari
- Pastda boshlash va tugash sanalari
- Ekranga kirganda chap-o'ng chizilish animatsiyasi
"Bu grafik — to'liq SwiftUI
PathvaGeometryReaderbilan qurilgan. Tashqi kutubxona yoki Chart framework ishlatilmagan. Bu naqadar kuchli!"
Keyingi darsda tavsifni kengaytiriladigan/qisqartiriladigan qilish va sozlamalar ekranini qo'shamiz. 🚀