SwiftUI如何从渐变中提取对应数值比例的单一Color色值
实现方案
核心逻辑是对绿色到红色的RGB通道做线性插值,直接计算对应比例的单一纯色,不需要依赖渐变视图做遮罩:
- 第一步:先计算当前消耗进度,把值约束在0~1区间内:
progress = min(max(monthTotalSpent / budgetdef, 0), 1) - 第二步:对RGB通道做插值:绿色的RGB参数为(红:0, 绿:1, 蓝:0),红色的RGB参数为(红:1, 绿:0, 蓝:0),对应通道数值 = 起始值 + (终点值 - 起始值) * 进度
- 红色通道值:0 + (1-0)*progress = progress
- 绿色通道值:1 + (0-1)*progress = 1 - progress
- 蓝色通道值固定为0
- 第三步:用计算出来的三个通道值生成单一Color,直接替换原来的渐变+遮罩方案即可。
修改后的完整代码如下:
import SwiftUI struct ContentView: View { @State private var monthTotalSpent = 100.0 @State private var budgetdef = 1100.0 // 计算当前状态对应的单一纯色 private var statusColor: Color { // 把进度约束在0~1之间,处理超过预算、数值小于0的异常情况 let progress = min(max(monthTotalSpent / budgetdef, 0), 1) // 绿到红的RGB插值计算 let redComponent = progress let greenComponent = 1 - progress return Color(red: redComponent, green: greenComponent, blue: 0) } var body: some View{ ZStack{ RoundedRectangle(cornerRadius: 30) .foregroundColor(.init(.systemGray4)) VStack(spacing: 5){ HStack{ Text("\(monthTotalSpent)") Text("/") Text("\(budgetdef)") } .padding(.top) .padding(.horizontal) ZStack(alignment: .center){ RoundedRectangle(cornerRadius: 15) .foregroundColor(Color(uiColor: .systemGray6)) .frame(width: UIScreen.main.bounds.width-50, height: 10, alignment: .center) HStack{ // 直接用计算出的单一纯色填充,不需要渐变和遮罩 RoundedRectangle(cornerRadius: 4) .foregroundColor(statusColor) .frame(width: ((monthTotalSpent*290)/budgetdef) < 290 ? ((monthTotalSpent*290)/budgetdef) : UIScreen.main.bounds.width-54, height: 8, alignment: .center) .padding(.leading, 27) Spacer(minLength: 0) } } Slider( value: $monthTotalSpent, in: 0...1500, step: 100 ) } } } }
如果需要过渡颜色更柔和,也可以调整蓝色通道为固定小值(比如0.1),或者改用HSV色彩模式插值调整饱和度,当前的RGB线性插值已经可以满足基础的绿到红平滑过渡需求。
内容的提问来源于stack exchange,提问作者newb
相关产品推荐
相关产品推荐

