Skip to content

Instantly share code, notes, and snippets.

@kaunteya
Last active July 23, 2024 15:58
Show Gist options
  • Save kaunteya/828aa10dd970c8b1396e2a3b37b56a6e to your computer and use it in GitHub Desktop.
Save kaunteya/828aa10dd970c8b1396e2a3b37b56a6e to your computer and use it in GitHub Desktop.
SwiftUI view that displays content gradually
//
// AnimatedText.swift
//
// Created by Kauntey Suryawanshi on 23/07/24.
//
import SwiftUI
struct AnimatedText: View {
enum Speed {
case fast, normal, slow
var duration: Duration {
switch self {
case .fast: .milliseconds(50)
case .normal: .milliseconds(100)
case .slow: .milliseconds(200)
}
}
/// Newline takes a longer wait
var durationNewLine: Duration {
switch self {
case .fast: .milliseconds(500)
case .normal: .milliseconds(1000)
case .slow: .milliseconds(2000)
}
}
}
let text: AttributedString
let speed: Speed
let wait: Duration
@State private var endIndex: AttributedString.Index
init(_ text: AttributedString, speed: Speed = .normal, wait: Duration = .zero) {
self.text = text
self.wait = wait
self.speed = speed
endIndex = self.text.startIndex
}
init(_ text: String, speed: Speed = .normal, wait: Duration = .zero) {
self.init(AttributedString(text), speed: speed, wait: wait)
}
var body: some View {
Group {
Text(AttributedString(text[text.startIndex ..< endIndex]))
+ Text(AttributedString(text[endIndex ..< text.endIndex]))
.foregroundColor(.clear)
}
.animation(.default, value: endIndex)
.task {
try? await Task.sleep(for: wait)
for i in text.characters.indices {
if text.characters[i].isNewline {
endIndex = i
try? await Task.sleep(for: speed.durationNewLine)
} else if text.characters[i].isWhitespace || text.characters.endIndex == i {
endIndex = i
try? await Task.sleep(for: speed.duration)
}
}
endIndex = text.endIndex
}
}
}
#Preview {
var attrString = AttributedString("Mark my words\n")
attrString.font = Font(NSFont.systemFont(ofSize: 21))
attrString.append(AttributedString("Long term capital gains for all asset classes is going to be 12.5%. You may worry about your stocks and equity funds. Actually that is very less of your concern.\nYou pay 2.5% more than earlier now."))
return VStack(alignment: .leading, spacing: 10) {
AnimatedText(attrString, speed: .normal)
}
.padding()
.frame(width: 500, height: 500)
}
@kaunteya
Copy link
Author

Demo

Untitled.mov

This SwiftUI view displays text gradually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment