53 lines
2.4 KiB
Swift
53 lines
2.4 KiB
Swift
import SwiftUI
|
|
|
|
/// Apple Intelligence 式多彩流光线:蓝→紫→粉→橙→青,横向无缝循环流动。
|
|
/// 全 App「AI 计算中」时刻的统一视觉点缀(日记 AI 辅助、身体档案报告生成/检索等待等)。
|
|
///
|
|
/// 注意:这条线的颜色是刻意走出 `Tj.Palette` 单色系统的 AI 高光点缀(应产品要求的
|
|
/// Apple 风格),仅此组件如此;其余 UI 仍严格守 §9 单色 token。
|
|
///
|
|
/// 驱动方式用 `TimelineView(.animation)` 而非 `.onAppear` + `repeatForever`:这条线出现的
|
|
/// 场景(流式回答、tok/s 每 0.5s 刷新等)父视图都在高频重绘,隐式 `repeatForever` 动画会被
|
|
/// 反复打断/重置 → 看起来「几乎不动」。TimelineView 按显示刷新率直接从时间算偏移,与父视图
|
|
/// 重绘完全解耦,任何场景下都匀速流动。
|
|
struct AIFlowBar: View {
|
|
var height: CGFloat = 3
|
|
/// 颜色平移一整圈(一个完整色序)的秒数,越小越快。
|
|
var cycle: Double = 0.6
|
|
|
|
private static let base: [Color] = [
|
|
Color(red: 0.35, green: 0.47, blue: 0.98), // 蓝
|
|
Color(red: 0.62, green: 0.36, blue: 0.92), // 紫
|
|
Color(red: 0.96, green: 0.40, blue: 0.62), // 粉
|
|
Color(red: 1.00, green: 0.55, blue: 0.30), // 橙
|
|
Color(red: 0.30, green: 0.80, blue: 0.92), // 青
|
|
]
|
|
|
|
/// 色序重复两遍并以首色收尾(共 11 个 stop,均匀分布):一个色周期恰好占据画布宽度,
|
|
/// 平移一个画布宽度后首尾同色,循环完全无缝。
|
|
private static let gradient: Gradient = {
|
|
let colors = base + base + [base[0]]
|
|
let last = CGFloat(colors.count - 1)
|
|
return Gradient(stops: colors.enumerated().map { i, c in
|
|
Gradient.Stop(color: c, location: CGFloat(i) / last)
|
|
})
|
|
}()
|
|
|
|
var body: some View {
|
|
TimelineView(.animation) { timeline in
|
|
GeometryReader { geo in
|
|
let w = geo.size.width
|
|
let t = timeline.date.timeIntervalSinceReferenceDate
|
|
let progress = CGFloat(t.truncatingRemainder(dividingBy: cycle) / cycle)
|
|
Capsule()
|
|
.fill(LinearGradient(gradient: Self.gradient,
|
|
startPoint: .leading, endPoint: .trailing))
|
|
.frame(width: w * 2)
|
|
.offset(x: -w * progress)
|
|
}
|
|
}
|
|
.frame(height: height)
|
|
.clipShape(Capsule())
|
|
}
|
|
}
|