Published on

SwiftUIda 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. SwiftUIda 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 - 1MagnificationGesture 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