You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:45:36