Swift 图表:绘制折线图,其中线条颜色由 Y 值决定

问题描述 投票:0回答:2

我正在尝试使用 Swift Charts 绘制下面的图表。我无法弄清楚如何根据 Y 值更改线条的颜色。在下图中,Y 的不同范围分配有不同的颜色,线条反映了这一点。

Desired Chart

我尝试使用 LineMark 的前景设置线条颜色,但它似乎只采用第一个颜色分配并忽略其上设置的任何其他颜色。

Chart {
    ForEach(plotItemSeries) { plotItem in
        LineMark(x: .value("XVAL", plotItem.xVal),
                 y: .value("YVAL", plotItem.yVal))
        .foregroundStyle(plotItem.zoneColor) // <== color assigned base on y-val
    }
}

Attempt #1

我尝试使用前景比例,但它只是将其分成多个系列,就像您所期望的那样。

Chart {
    ForEach(plotItemSeries) { plotItem in
        LineMark(x: .value("XVAL", plotItem.xVal),
                 y: .value("YVAL", plotItem.yVal))
        .foregroundStyle(by: .value("Zone", plotItem.zoneColorName)) // <== "gray", "blue", etc..
    }
}
.chartForegroundStyleScale(["gray": Color("grayCustom"),
                            "green": Color("greenCustom"),
                            "blue": Color("blueCustom"),
                            "orange": Color("orangeCustom"),
                            "red": Color("redCustom")])

Attempt #2

有什么想法如何根据 y 值设置线条的颜色吗?

ios swiftui charts
2个回答
2
投票

事实证明

.linearGradient(_ gradient: Gradient, startPoint: UnitPoint, endPoint: UnitPoint) -> LinearGradient
是正确的方法。 Gradient.Stops 映射到 UnitPoint,UnitPoint 映射到所绘制线条的边界框,因此颜色边界 y 值必须转换为单位点值,该值映射到颜色边界的 y 值。

举个简单的例子,如果我们想在 5 的 y-val 下面画蓝色线,上面画绿色线,并且该线是:(0,0) 到 (10,10) 则对应于转换的单位点值点是0.5。

为了获得清晰的颜色过渡,我们只需定义渐变,以便颜色变化的部分太小而无法渲染:

let stops = [
  Gradient.Stop(color: .red, location: 0.0),
  Gradient.Stop(color: .red, location: 0.5),
  Gradient.Stop(color: .green, location: 0.50001),
  Gradient.Stop(color: .green, location: 1.0)
]

因此,正确的方法看起来像:

Chart {
  ForEach(plotItemSeries) { plotItem in
      LineMark(x: .value("XVAL", plotItem.xVal),
               y: .value("YVAL", plotItem.yVal))
      .foregroundStyle(.linearGradient(Gradient(stops: stops),
                                       startPoint: .bottom,
                                       endPoint: .top))
  }
}

生成的图形线(使用原始数据)看起来与我们试图匹配的原始图形接近:Graph With SwiftCharts


0
投票

你可以尝试一下,这可能就是你想要实现的目标。

Chart {
    ForEach(plotItemSeries) { plotItem in
        LineMark(x: .value("XVAL", plotItem.xVal),
                 y: .value("YVAL", plotItem.yVal))
        .foregroundStyle(
                .linearGradient(
                // You can have more colours here depends on your data.
                colors: [.blue, .red],
                startPoint: .bottom,
                endPoint: .top)
            )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.