Skip to content

Instantly share code, notes, and snippets.

@mattyoung
Last active October 26, 2024 11:57
Show Gist options
  • Save mattyoung/52947aff8524ed3c86d6ebd695dcfc86 to your computer and use it in GitHub Desktop.
Save mattyoung/52947aff8524ed3c86d6ebd695dcfc86 to your computer and use it in GitHub Desktop.
//
// !!! SwiftUI 3: use .foregroundStyle()! Much simplified
//
import SwiftUI
import os
let logger = Logger(subsystem: "net.hddigitalworks.TextColorAnimate", category: "color")
// all five (so far) ways to animate Text foreground color
struct TextColorAnimate: View {
@State private var flag = false
var body: some View {
VStack {
// 1) the best! Thanks @SwiftUILab !!
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.white)
.colorMultiply(flag ? .green : .red)
// 2)
if flag {
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.green)
} else {
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.red)
}
// 3)
ZStack {
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.green)
.opacity(flag ? 0 : 1)
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.red)
.opacity(flag ? 1 : 0)
}
// 4
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.modifier(ColorAnimation(flag, from: .green, to: .red))
// 5)
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.clear)
.overlay(
Rectangle()
.foregroundColor(flag ? .green : .red)
.mask(Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle))
)
Text("So that redacted is animated!")
Text("Lorem Ipsum deldor \(Image(systemName: "externaldrive.fill.badge.plus"))").font(.largeTitle)
.foregroundColor(.white)
.colorMultiply(flag ? .green : .red)
.redacted(reason: .placeholder)
}
.onAppear {
withAnimation(Animation.linear(duration: 2).repeatForever()) {
flag.toggle()
}
}
}
}
// copied (mostly) from https://swiftui-lab.com/swiftui-animations-part3/
struct ColorAnimation: AnimatableModifier {
var animatableData: Double
let rgbaPair: [(Double, Double)]
static private let garbage = [(0.0, 1.0), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0)]
init(_ flag: Bool, from: Color, to: Color) {
animatableData = flag ? 0 : 1
guard let cc1 = UIColor(from).cgColor.components else {
rgbaPair = Self.garbage
logger.error("ColorAnimation: UIColor(from).cgColor.components return nil!!")
return
}
guard let cc2 = UIColor(to).cgColor.components else {
rgbaPair = Self.garbage
logger.error("ColorAnimation: UIColor(to).cgColor.components return nil!!")
return
}
rgbaPair = Array(zip(cc1.map(Double.init), cc2.map(Double.init)))
}
func body(content: Content) -> some View {
content
.foregroundColor(mixedColor)
}
// This is a very basic implementation of a color interpolation
// between two values.
var mixedColor: Color {
let rgba = rgbaPair.map { $0.0 + ($0.1 - $0.0) * animatableData }
return Color(red: rgba[0], green: rgba[1], blue: rgba[2], opacity: rgba[3])
}
}
struct TextColorAnimate_Previews: PreviewProvider {
static var previews: some View {
TextColorAnimate()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment