Site icon AppTractor

Примеры анимации SF-символов в SwiftUI

На WWDC’23 была представлена анимация SF-символов. Имеется 7 различных предустановок анимации: появление, исчезновение, отскок, масштабирование, импульс, смена цвета и замена.

Каждый из этих пресетов имеет свое применение:

Анимация символов применяется с помощью symbolEffect(_:options:value:) для дискретных эффектов, symbolEffect(_:options:isActive:) для бесконечных эффектов и view-модификаторами contentTransition(_:) и transition() с новым symbolEffect. Дискретные эффекты являются on-off эффектами, в то время как бесконечные эффекты изменяют символ неограниченно и требуют явного прекращения. Отскок, пульсация и смена цвета это дискретные эффекты, а пульсация, замена, появление и исчезновение — бесконечные. Появление и исчезновение также поддерживают эффекты перехода, а замена — эффект перехода по содержимому. Поэтому при выборе модификатора вида необходимо помнить об этом.

Далее рассмотрим некоторые примеры и способы применения этих модификаторов вида.

Появление и исчезновение

struct AppearDisappearView: View {
    @State private var isDrizzleHidden = true

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: "cloud.fill")
                Image(systemName: "cloud.drizzle.fill")
                    .symbolEffect(.disappear, isActive: isDrizzleHidden)
                Image(systemName: "cloud.heavyrain.fill")
            }
            .imageScale(.large)
            HStack {
                Image(systemName: "cloud.fill")
                if !isDrizzleHidden {
                    Image(systemName: "cloud.drizzle.fill")
                        .transition(.symbolEffect(.automatic))
                }
                Image(systemName: "cloud.heavyrain.fill")
            }
            .imageScale(.large)
            Button("Appear/Disapper") {
                isDrizzleHidden.toggle()
            }
        }
    }
}

Отскок

struct BounceView: View {
    @State private var value = 0

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: "snowflake")
                    .symbolEffect(.bounce, value: value)
                Image(systemName: "snowflake")
                    .symbolEffect(.bounce, options: .speed(0.1), value: value)
                Image(systemName: "snowflake")
                    .symbolEffect(.bounce, options: .repeat(2), value: value)

            }
            .imageScale(.large)
            Button("Bounce") { value += 1 }
        }
    }
}

Масштабирование

struct ScaleView: View {
    @State private var isActive = false

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: "drop.fill")
                    .symbolEffect(.scale.up, isActive: isActive)
                Image(systemName: "drop.fill")
                    .symbolEffect(.scale.down, options: .speed(0.1), isActive: isActive)
                Image(systemName: "drop.fill")
                    .symbolEffect(.scale.down, options: .speed(5), isActive: isActive)

            }
            .imageScale(.large)
            Button("Scale") { isActive.toggle() }
        }
    }
}

Пульсация

struct PulseView: View {
    @State private var isActive = false

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: "moonphase.first.quarter")
                    .symbolEffect(.pulse, isActive: isActive)
                Image(systemName: "moonphase.first.quarter")
                    .symbolEffect(.pulse, options: .speed(0.1), isActive: isActive)
                Image(systemName: "moonphase.first.quarter")
                    .symbolEffect(.pulse, options: .speed(5), isActive: isActive)

            }
            .imageScale(.large)
            Button("Pulse") { isActive.toggle() }
        }
    }
}

Смена цвета

struct VariableColorView: View {
    @State private var isActive = false

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: "rainbow")
                    .symbolEffect(.variableColor, options: .speed(0.1), isActive: isActive)
                Image(systemName: "rainbow")
                    .symbolEffect(.variableColor.iterative, options: .speed(0.1), isActive: isActive)
                Image(systemName: "rainbow")
                    .symbolEffect(.variableColor.iterative.reversing, options: .speed(0.1), isActive: isActive)

            }
            .symbolRenderingMode(.multicolor)
            .imageScale(.large)
            Button("Variable Color") { isActive.toggle() }
        }
    }
}

Замена

struct ReplaceView: View {
    @State private var isActive = false

    var body: some View {
        VStack(spacing: 16) {
            HStack {
                Image(systemName: isActive ? "pause.circle.fill" : "play.circle.fill")
                    .contentTransition(.symbolEffect(.replace))
                Image(systemName: isActive ? "pause.circle.fill" : "play.circle.fill")
                    .contentTransition(.symbolEffect(.replace.offUp))
                Image(systemName: isActive ? "pause.circle.fill" : "play.circle.fill")
                    .contentTransition(.symbolEffect(.replace.upUp))
            }
            .imageScale(.large)
            Button("Replace") { isActive.toggle() }
        }
    }
}

Пример проекта SymbolsAnimationExample (Xcode 15 beta 6)

Если это было полезно, сообщите мне об этом по адресу Mastodon@toomasvahter или в Twitter @toomasvahter. Не стесняйтесь подписываться на RSS-ленту. Спасибо, что читаете.

Источник

Exit mobile version