SwiftUI AngularGradient环形渐变过渡生硬,如何实现平滑过渡效果?
优化方案
你当前实现渐变生硬核心有两个问题:
- AngularGradient固定配置为360度全范围渐变,但实际绘制时用
trim只截取了部分环形,相当于只取了完整渐变的一个截断片段,自然没有平滑的过渡效果 - 渐变仅设置了红、绿两个极端色,中间没有过渡色阶,进度变化时色彩跳变感强
具体优化点
- 动态匹配渐变角度和当前进度:把AngularGradient的
endAngle改为和当前进度成正比的角度,而非固定360度,让渐变范围完全匹配你要绘制的环形长度 - 补充过渡色值:在红、绿之间增加中间过渡色,让色彩变化更顺滑
- 满环状态下做首尾衔接:如果需要进度100%时环形没有颜色断层,可在渐变首尾增加相同的颜色值做过渡
优化后代码
struct DiskSizeInfoView: View { // 总容量、已用容量可自行传入修改 let total: Double = 1024 let used: Double = 512 // 计算进度和对应角度 private var progress: Double { used / total } private var gradientEndAngle: Angle { .degrees(progress * 360) } var body: some View { ZStack { Circle() .stroke(Color(UIColor.secondarySystemBackground), lineWidth: 30) Circle() .trim(from: 0, to: progress) .stroke( AngularGradient( // 增加中间过渡色橙色,也可根据需求加更多色阶 gradient: Gradient(colors: [Color.red, Color.orange, Color.green]), center: .center, startAngle: .zero, // 渐变结束角度和进度匹配 endAngle: gradientEndAngle ), style: StrokeStyle(lineWidth: 30, lineCap: .round, lineJoin: .round) ) .rotationEffect(Angle(degrees: -90)) // 调整起始位置到顶部,无需额外3D翻转 Text("\(Int(used))") .font(.system(size: 30, weight: .bold, design: .rounded)) } .frame(width: 300, height: 300) } }
额外说明
如果需要满环(progress=1)时首尾颜色平滑衔接,可把渐变调整为Gradient(colors: [Color.green, Color.red, Color.orange, Color.green]),这样首尾都是绿色,360度衔接不会有断层。
如果对渐变精度要求更高,还可以用Gradient(stops: [])自定义每个色值对应的角度位置,精准控制渐变过渡节奏。
内容的提问来源于stack exchange,提问作者Ufuk Köşker
相关产品推荐
相关产品推荐

