Site icon AppTractor

Осваиваем пружинную анимацию в SwiftUI

В SwiftUI анимации действительно мощные, и среди них пружинная анимация даёт реалистичное и плавное ощущение — как будто элементы двигаются естественно, с эффектом отскока и переразгона (overshoot).

Если вы замечали, что при лёгком нажатии на кнопку или карточку появляется небольшой эффект подпрыгивания — это и есть пружинная анимация.

В SwiftUI мы можем реализовать пружинную анимацию с помощью следующих операторов:

withAnimation(.spring()) {
    // write code
}

Модификатор:

.animation(.spring(), value: isExpanded)

Давайте разберёмся с пружинной анимацией на примерах кода.

1. withAnimation

Как видите, при нажатии на текст появляется эффект подпрыгивания (bouncy effect), известный как пружинная анимация.

Код:

struct ContentView: View {
    
    @State private var scale: CGFloat = 1.0
    
    var body: some View {
        Button("Tap Me") {
            withAnimation(.spring()) {
                scale = scale == 1.0 ? 1.5 : 1.0
            }
        }
        .scaleEffect(scale)
        .font(.largeTitle)
    }
}

Здесь мы использовали функцию withAnimation, которая принимает тип анимации (в нашем случае — .spring()), а внутри блока изменяем состояние scale в зависимости от условия.

Модификатор scaleEffect отвечает за масштабирование текста.

Это была стандартная пружинная анимация, но если нужен более тонкий контроль, функция spring() принимает дополнительные параметры.

1. response

Определяет, насколько быстро анимация реагирует на изменения.

.spring(response: 0.3)  // quick
.spring(response: 0.5) // Default value
.spring(response: 0.8) // slower

В зависимости от ваших требований, вы можете выбрать любое значение от 0,1 до 1.

2. dampingFraction

Определяет, насколько сильным будет отскок.

> 1.0 // greater than 1, less bounce
< 1.0 // less than 1 , more bounce

Если вы передадите значение больше 1, отскок будет менее сильным, а если значение меньше 1, то отскок будет сильнее (он может отскочить, как мяч, 2-3 раза).

.spring(dampingFraction: 0.3) // more bouncy
.spring(dampingFraction: 2) // less bouncy

3. blendDuration

Этот параметр управляет временем смешивания анимаций (используется редко).

.spring(blendDuration: 0.2)

Пружинная анимация включает две подкатегории, которые дают больше контроля.

1. Interpolating Spring

Если вам нужно более реалистичное поведение с точки зрения физики — используйте интерполирующую пружину (interpolating spring).

Код:

struct ContentView: View {
    
    @State private var scale: CGFloat = 1.0
    
    var body: some View {
        Button("Tap Me") {
            withAnimation(.interpolatingSpring(
                mass: 1.0,
                stiffness: 1,
                damping: 10,
                initialVelocity: 2
            )) {
                scale = scale == 1.0 ? 1.5 : 1.0
            }
        }
        .scaleEffect(scale)
        .font(.largeTitle)
    }
}

Здесь:

Теперь анимация выглядит более контролируемой.

2. Interactive Spring

Этот тип пружины в основном используется с анимацией, управляемой жестами.

Давайте разберемся на примере:

Как видите, когда я двигаю объект влево и вправо, он отскакивает обратно с пружинящим эффектом.

Код:

struct ContentView: View {
    
    @State private var offset: CGFloat = 0
    
    var body: some View {
        RoundedRectangle(cornerRadius: 16)
            .foregroundStyle(.blue)
            .frame(width: 200, height: 80)
            .offset(x: offset)
            .gesture(
                DragGesture()
                    .onChanged { value in
                        offset = value.translation.width
                    }
                    .onEnded { _ in
                        withAnimation(.interactiveSpring()) {
                            offset = 0
                        }
                    }
            )
    }
    
}

Как видите, мы добавили интерактивную пружинную анимацию после завершения жеста.

2. Модификатор animation(_:value:)

Есть ещё один способ реализовать пружинную анимацию — с помощью модификатора animation(_:value:).

Давайте разберёмся на примере:

Как видите, при нажатии на кнопку-переключатель для прямоугольника запускается пружинная анимация.

struct ContentView: View {
    
    @State private var isExpanded = false
    
    var body: some View {
        VStack {
            Rectangle()
                .fill(Color.blue)
                .frame(
                    width: isExpanded ? 200 : 100,
                    height: isExpanded ? 200 : 100
                )
                .animation(.spring(), value: isExpanded)
            
            Button("Toggle") {
                isExpanded.toggle()
            }
        }
    }
}

Здесь мы использовали .spring() внутри модификатора animation, чтобы создать пружинную анимацию.

Итог

Используйте пружинную анимацию, когда:

Источник

Exit mobile version