Swift Charts中按开盘收盘价设置K线图RectangleMark独立颜色
解决K线图颜色区分问题
你的问题核心在于用单个@State变量chartColor存储颜色,循环遍历数据时会不断覆盖这个变量,最终所有K线都会使用最后一条数据计算出的颜色。而且在视图更新时修改状态会触发警告,这是因为SwiftUI不允许在视图渲染过程中改变状态。
正确的做法是为每一条K线数据单独计算颜色,不需要全局的状态变量。直接在RectangleMark的foregroundStyle里根据当前数据的开盘价和收盘价判断颜色即可。
另外注意不要强制解包Double转换的结果,建议用guard let处理可选值,避免崩溃。
修改后的代码如下:
import SwiftUI import Charts struct CoinChart: View { @ObservedObject var chartManager: ChartManager var body: some View { VStack { Chart{ ForEach(chartManager.chartData.data, id: \.self) { chartData in let date = chartManager.unixConverter(unixTime: Double(chartData.period)) // 安全处理价格转换,避免强制解包 guard let lowPrice = Double(chartData.low), let highPrice = Double(chartData.high), let openPrice = Double(chartData.open), let closePrice = Double(chartData.close) else { return // 转换失败则不绘制该K线 } // 计算当前K线的颜色 let barColor: Color = closePrice < openPrice ? .red : .green // 绘制上下影线 RectangleMark(x: .value("Time", date), yStart: .value("Low Price", lowPrice), yEnd: .value("High Price", highPrice), width: 1) .foregroundStyle(barColor) // 绘制实体部分 RectangleMark(x: .value("Time", date), yStart: .value("Open Price", openPrice), yEnd: .value("Close Price", closePrice), width: 6) .foregroundStyle(barColor) } } .chartYScale(domain: 18000...21000) .chartXAxis { AxisMarks(position: .bottom) { _ in AxisGridLine().foregroundStyle(.clear) AxisTick().foregroundStyle(.clear) AxisValueLabel() } } .frame(height: 300) Text(String(chartManager.chartData.data.count)) } .task { await chartManager.loadChartData() } } }
关键修改点:
- 移除了
@State var chartColor和colorChange()函数,避免状态管理错误 - 对价格转换做了安全处理,用
guard let替代强制解包 - 为每一条K线数据单独计算
barColor,确保每个K线颜色独立 - 直接在
foregroundStyle中使用计算好的颜色,无需依赖全局状态
内容的提问来源于stack exchange,提问作者Jono Then
相关产品推荐
相关产品推荐

