Published on

SwiftUI-da MagnificationGesture-dan qanday foydalanish kerak

Authors

MagnificationGesture nima

MagnificationGesture β€” bu iPhone-dagi xaritada yoki Instagram-da rasmda ikki barmog'ingizni ochib-yopib kattalashtirish/kichraytirish gesture-i. SwiftUI-da buni istalgan elementga qo'shish mumkin.


Yangi fayl yaratish

MagnificationGestureBootcamp nomli yangi SwiftUI View fayl yaratamiz.


Oddiy misol

@State private var currentAmount: CGFloat = 0

var body: some View {
    Text("Hello, World!")
        .font(.title)
        .padding(40)
        .background(Color.red)
        .cornerRadius(10)
        .scaleEffect(1 + currentAmount)
        .gesture(
            MagnificationGesture()
                .onChanged { value in
                    currentAmount = value - 1
                }
        )
}
  • .gesture(MagnificationGesture()) β€” gesture-ni elementga qo'shish usuli. Oldingi videodagi LongPressGesture o'rniga bu yerda MagnificationGesture ishlatiladi β€” tuzilma bir xil.
  • .scaleEffect(1 + currentAmount) β€” 1.0 = hozirgi o'lcham (100%). currentAmount qo'shilishi o'lchamni oshiradi yoki kamaytiradi.
  • value - 1 β€” MagnificationGesture qiymati 1.0dan boshlanadi (o'zgarish yo'q). Biz 0dan boshlashni xohlayganmiz, shuning uchun 1 ayiramiz.

Eslatma: Simulator-da ikki barmog'ini ko'rsatish uchun Option tugmasini bosib ushlab turing, so'ngra bosing va torting.


Muammo: gesture qayta boshlanishi

Birinchi gesture-dan so'ng qo'l ko'tarilib, qayta boshlanilsa, element boshlang'ich o'lchamiga qaytib "sakrab" tushadi. Buning sababi β€” currentAmount har safar 0dan boshlanadi.

Yechim: lastAmount qo'shish

@State private var currentAmount: CGFloat = 0
@State private var lastAmount: CGFloat = 0

var body: some View {
    Text("Hello, World!")
        .font(.title)
        .padding(40)
        .background(Color.red)
        .cornerRadius(10)
        .scaleEffect(1 + currentAmount + lastAmount)
        .gesture(
            MagnificationGesture()
                .onChanged { value in
                    currentAmount = value - 1
                }
                .onEnded { value in
                    lastAmount += currentAmount
                    currentAmount = 0
                }
        )
}
  • lastAmount β€” oldingi gesture tugaganidagi umumiy o'zgarishni saqlaydi
  • onEnded β€” gesture tugatilganda: lastAmountga currentAmount qo'shiladi, currentAmount esa 0 ga qaytadi
  • scaleEffect(1 + currentAmount + lastAmount) β€” joriy va avvalgi o'zgarishlar birgalikda hisoblanadi

Endi gesture qayta boshlanganida, element oxirgi o'lchamidan davom etadi β€” "sakrab" qaytmaydi.


Amaliy misol: Instagram uslubida rasm zoom

Endi bu gesture-ni haqiqiy ilovaga o'xshash kontekstda ko'ramiz: Instagram-da rasm ustida ikki barmog'ingizni qo'yib kattalashtirish, qo'l ko'tarilganda esa orqaga qaytish.

@State private var currentAmount: CGFloat = 0

var body: some View {
    VStack(spacing: 10) {

        // Profil qatori (header)
        HStack {
            Circle()
                .frame(width: 35, height: 35)

            Text("swiftful_thinking")

            Spacer()

            Image(systemName: "ellipsis")
        }
        .padding(.horizontal)

        // Rasm (hozircha to'rtburchak)
        Rectangle()
            .frame(height: 300)
            .scaleEffect(1 + currentAmount)
            .gesture(
                MagnificationGesture()
                    .onChanged { value in
                        currentAmount = value - 1
                    }
                    .onEnded { value in
                        withAnimation(.spring()) {
                            currentAmount = 0
                        }
                    }
            )

        // Like va kommentariya qatori
        HStack {
            Image(systemName: "heart.fill")
            Image(systemName: "text.bubble.fill")
            Spacer()
        }
        .font(.headline)
        .padding(.horizontal)

        // Caption
        Text("This is the caption for my photo πŸ“Έ")
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(.horizontal)
    }
}

Oddiy misoldagi lastAmountdan farq

Bu Instagram misolida onEnded-da currentAmount = 0 ga qaytariladi β€” ya'ni qo'l ko'tarilganda element o'z asl o'lchamiga qaytadi. Aynan Instagram-dagi xulq: zoom qilasiz, qo'l ko'tarasiz β€” rasm orqaga qaytadi.

withAnimation(.spring()) qo'shilishi tufayli qaytish silliq va tabiiy ko'rinadi.


onChanged vs onEnded β€” ikkala misol solishtirma

Oddiy misolInstagram misoli
onChangedcurrentAmount = value - 1currentAmount = value - 1
onEndedlastAmount += currentAmount; currentAmount = 0withAnimation { currentAmount = 0 }
NatijaO'lcham saqlanadiO'lcham orqaga qaytadi

Gesture-larning umumiy tuzilmasi

Keyingi videolardagi gesture-lar ham xuddi shu tuzilmaga ega β€” faqat gesture turi o'zgaradi:

.gesture(
    MagnificationGesture()   // ← shu qator o'zgaradi
        .onChanged { value in
            // joriy holat
        }
        .onEnded { value in
            // tugash holati
        }
)

Bu pattern-ni yaxshi o'zlashtirib olish β€” keyingi gesture-larni o'rganishni ancha osonlashtiradi.

Buy mea coffee