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

Анимации в SwiftUI создаются с помощью замыкания withAnimation, которому передается блок кода, изменяющий состояние представления. SwiftUI автоматически анимирует изменения состояния, происходящие в замыкании withAnimation, интерполируя значения свойств от их начальных значений до их конечных значений в течение заданного времени. Платформа также предоставляет ряд встроенных анимаций, таких как базовые преобразования (масштабирование, поворот и т. д.), затухание и многое другое, которые можно легко добавить в представления.

struct AnimatedCircle: View {
    @State private var scale: CGFloat = 1.0

    var body: some View {
        Circle()
            .fill(Color.red)
            .frame(width: 100, height: 100)
            .scaleEffect(scale)
            .onTapGesture {
                withAnimation {
                    self.scale += 0.1
                }
            }
    }
}

В этом примере структура AnimatedCircle определяет представление Circle с модификатором scaleEffect, который изменяет размер круга. При касании круга свойство состояния scale увеличивается на 0.1, а замыкание withAnimation используется для анимации изменения. Анимация будет интерполировать переход от исходного размера круга к его новому размеру в течение продолжительности по умолчанию 0.25 секунд. Вы можете настроить продолжительность анимации, временную кривую и другие параметры, передав аргументы замыканию withAnimation.

SwiftUI также предоставляет возможность создавать собственные анимации с использованием протокола Animatable. Этот протокол позволяет вам определять настраиваемые анимируемые свойства и то, как они должны интерполироваться во время анимации. Например, вы можете определить пользовательское анимируемое свойство для цвета и указать способ перехода цвета от одного значения к другому во время анимации. например:

struct AnimatedRectangle: View {
    @State private var animatableValue: Double = 0

    var body: some View {
        Rectangle()
            .fill(Color.blue)
            .frame(width: 200, height: 100)
            .cornerRadius(CGFloat(animatableValue))
            .onTapGesture {
                withAnimation(.interactiveSpring()) {
                    self.animatableValue = 20
                }
            }
    }
}

В этом примере у нас есть представление Rectangle с модификатором cornerRadius, который принимает значение CGFloat. Свойство состояния animatableValue объявлено как Double, но оно преобразуется в CGFloat при передаче модификатору cornerRadius. При касании прямоугольника animatableValue устанавливается на 20 внутри замыкания withAnimation, что запускает анимацию для интерполяции изменения исходного значения на новое значение. Используется анимация .interactiveSpring(), которая создает пружинящую анимацию, реагирующую на скорость жеста.

Чтобы сделать тип Double анимируемым, мы можем соответствовать протоколу Animatable и предоставить метод .animation:

extension Double: Animatable {
    public var animatableData: Double {
        get { self }
        set { self = newValue }
    }

    public typealias AnimatableData = Double
}

Благодаря этой реализации тип Double теперь можно использовать в качестве анимируемого свойства в анимациях SwiftUI.

Как всегда, весь код можно скачать с моей страницы на github.