Программирование
Примеры анимации SF-символов в SwiftUI
Имеется 8 различных предустановок анимации: появление, исчезновение, отскок, масштабирование, импульс, смена цвета и замена.
На WWDC’23 была представлена анимация SF-символов. Имеется 7 различных предустановок анимации: появление, исчезновение, отскок, масштабирование, импульс, смена цвета и замена.
Каждый из этих пресетов имеет свое применение:
- Анимация появления используется при первом отображении символа в пользовательском интерфейсе.
- Анимация исчезновения используется при удалении символа из пользовательского интерфейса.
- Анимация отскока используется для сообщения пользователю о том, что действие было запущено или успешно завершено.
- Анимация масштабирования подходит для выделения элементов в пользовательском интерфейсе, например при наведении курсора на элемент. Она также может использоваться для того, чтобы сообщить пользователю о том, что действие совершилось (вспомните кнопку, которая находится в нажатом состоянии).
- Импульсная анимация — отличный способ показать, что какое-то действие продолжается. Например, во время записи видеоролика символ кнопки записи пульсирует.
- Анимация смены цвета передает состояние, которое меняется со временем (например, уровень сигнала Wi-Fi).
- Анимация замены полезна для передачи информации об изменении функции. Например, кнопка воспроизведения сменяется кнопкой паузы.
Анимация символов применяется с помощью 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()
}
}
}
}
Отскок
xxxxxxxxxx
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 }
}
}
}
Масштабирование
xxxxxxxxxx
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() }
}
}
}
Пульсация
xxxxxxxxxx
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() }
}
}
}
Смена цвета
xxxxxxxxxx
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() }
}
}
}
Замена
xxxxxxxxxx
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-ленту. Спасибо, что читаете.
-
Видео и подкасты для разработчиков4 недели назад
Как устроена мобильная архитектура. Интервью с тех. лидером юнита «Mobile Architecture» из AvitoTech
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.10
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.11
-
Видео и подкасты для разработчиков2 недели назад
Javascript для бэкенда – отличная идея: Node.js, NPM, Typescript