Разработка
Создаем анимацию печати текста на печатной машинке в SwiftUI
Одним из особенно интересных эффектов является анимация печатной машинки, когда текст появляется символ за символом, как будто его набирают в режиме реального времени.
Анимация текста может значительно улучшить впечатления пользователя от приложения, добавив ему динамичности и интерактивности. Одним из особенно интересных эффектов является анимация печатной машинки, когда текст появляется символ за символом, как будто его набирают в режиме реального времени. Например, такая анимация особенно актуальна для платформ чатов с искусственным интеллектом. На самом деле, я использовал именно эту анимацию в процессе регистрации в своем приложении Catzumi, создавая ретро-стиль и запоминающееся первое впечатление для новых пользователей.
В этой статье мы рассмотрим, как реализовать этот эффект в SwiftUI, создав многоразовое представление AnimatedText
, которое оживит ваш текст.
Понимаем концепцию
Прежде чем погрузиться в код, давайте разберем основную идею, лежащую в основе анимации печатной машинки:
- Мы начинаем с пустой строки и постепенно показываем каждый символ.
- Для управления видимостью символов мы используем
AttributedString
. - Для создания эффекта печатания мы используем рекурсивную функцию с задержкой.
Использование AttributeString
вместо добавления каждого символа по одному позволяет избежать проблем с версткой.
Реализация кода
Давайте рассмотрим реализацию нашего представления AnimatedText
.
import SwiftUI struct AnimatedText: View { // MARK: - Inits init(_ text: Binding<String>) { self._text = text var attributedText = AttributedString(text.wrappedValue) attributedText.foregroundColor = .clear self._attributedText = State(initialValue: attributedText) } // MARK: - Properties (Private) @Binding private var text: String @State private var attributedText: AttributedString // MARK: - Properties (View) var body: some View { Text(attributedText) .onAppear { animateText() } .onChange(of: text) { animateText() } } // MARK: - Methods (Private) private func animateText(at position: Int = 0) { if position <= text.count { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { let stringStart = String(text.prefix(position)) let stringEnd = String(text.suffix(text.count - position)) let attributedTextStart = AttributedString(stringStart) var attributedTextEnd = AttributedString(stringEnd) attributedTextEnd.foregroundColor = .clear attributedText = attributedTextStart + attributedTextEnd animateText(at: position + 1) } } else { attributedText = AttributedString(text) } } }
Инициализация
init(_ text: Binding<String>) { self._text = text var attributedText = AttributedString(text.wrappedValue) attributedText.foregroundColor = .clear self._attributedText = State(initialValue: attributedText) }
Мы инициализируем наше представление с биндингом к String
. Мы создаем AttributedString
из этого текста и первоначально устанавливаем его цвет на clear, делая его невидимым.
View Body
var body: some View { Text(attributedText) .onAppear { animateText() } .onChange(of: text) { animateText() } }
В представлении отображается attributedText
. Мы запускаем анимацию при появлении представления и при изменении текста.
Логика анимации
private func animateText(at position: Int = 0) { if position <= text.count { DispatchQueue.main.asyncAfter(deadline: .now() + 0.075) { let stringStart = String(text.prefix(position)) let stringEnd = String(text.suffix(text.count - position)) let attributedTextStart = AttributedString(stringStart) var attributedTextEnd = AttributedString(stringEnd) attributedTextEnd.foregroundColor = .clear attributedText = attributedTextStart + attributedTextEnd animateText(at: position + 1) } } else { attributedText = AttributedString(text) } }
Эта рекурсивная функция — сердце нашей анимации:
- Мы разделим текст на две части: видимую и невидимую.
- Мы создаем атрибутированные строки для обеих частей, устанавливая для конечной части цвет clear.
- Мы объединяем эти части и обновляем наш
attributedText
. - Мы снова вызываем функцию со следующей позицией после небольшой задержки в
0.075
секунды. - Когда мы дойдем до конца текста, мы сделаем весь текст видимым.
Использование представления AnimatedText
Чтобы использовать это представление в своем приложении SwiftUI, вы можете просто сделать следующее:
struct ContentView: View { // MARK: - Properties (Private) @State private var text = "Hello, SwiftUI!" // MARK: - Properties (View) var body: some View { AnimatedText($text) } }
Преимущества
Внедрение анимации печатной машинки в процесс регистрации в Catzumi дало несколько выгод.
- Повышение вовлеченности: Динамичный текст заинтересовывает пользователей и побуждает их дочитать до конца.
- Темп подачи информации: Постепенно раскрывая текст, мы даем пользователям время усвоить каждый фрагмент информации, прежде чем переходить к следующему.
- Индивидуальность: Эффект набора текста придает приложению индивидуальность, делая его более интерактивным и живым.
- Снижение перегруженности: В приложениях со сложными функциями эта техника побуждает разработчика разбивать информацию на легко усваиваемые фрагменты, снижая риск перегрузить новых пользователей.
Заключение
Представление AnimatedText
обеспечивает изящную, настраиваемую анимацию печатной машинки для ваших приложений SwiftUI. Используя декларативный синтаксис SwiftUI и возможности AttributedString
, мы создали компонент многократного использования, который может придать динамичность любому тексту в вашем приложении.
Помните, что анимация может улучшить пользовательский опыт, но использовать ее следует с умом. Учитывайте контекст и частоту использования, чтобы убедиться, что она приносит пользу, а не отвлекает. Например, использование эффекта печатной машинки только в процессе регистрации может служить четкой цели ознакомления новых пользователей с концепцией и возможностями приложения.