如何使用Apple的SwiftUI图表创建所需的图表?
Desired Chart(实体模型)-包含数据点的阶梯形曲线图为蓝色,趋势线为红色:
需要将趋势线添加到包含阶梯线图的现有图表中.除了使用另一个LineMark之外,SwiftUI图表标记似乎不适用于倾斜趋势线.
下面提供的趋势线代码仅在与散点图(PointMark)一起使用时有效.但当趋势线与线性图(即另一个LineMark)一起使用时,趋势线就会成为第一个LineMark的延续.当使用两个LineMark时,第二个LineMark上的修改器将被忽略.
Unwanted Result -当在SwiftUI图表中使用两个LineMarks时,这是不需要的结果,而不是上面的图表:
然而,当删除另一个LineMark时,趋势线代码会按照预期工作:
包含示例数据的完整示例代码:
import SwiftUI
import Charts
struct ContentView: View {
@State var showSteps: Bool = false
@State var showTrend: Bool = false
var body: some View {
VStack {
Chart {
//Main data
ForEach(dataPoints.filter({ data in data.type == .data}), id: \.id) { point in
if showSteps {
LineMark(
x: PlottableValue.value("Date", point.date),
y: PlottableValue.value("Amount", point.amount)
)
.interpolationMethod(.stepEnd)
}
PointMark(
x: .value("Date", point.date),
y: .value("Amount", point.amount)
)
}
// Trend line
if showTrend {
ForEach(dataPoints.filter({ data in data.type == .trend}), id: \.id) { trend in
LineMark(
x: PlottableValue.value("Date", trend.date),
y: PlottableValue.value("Amount", trend.amount)
)
.foregroundStyle(Color.red)
.lineStyle(StrokeStyle(lineWidth: 5))
.interpolationMethod(.linear)
}
}
}
.padding(.all)
.frame(height: 500)
.chartXScale(domain: Date(timeIntervalSinceNow: 3600 * 24 * -15) ... Date(timeIntervalSinceNow: 3600 * 24 * 15))
.chartYAxis {
AxisMarks(preset: .aligned, position: .automatic, values: .stride(by: 5)) {
let value = $0.as(Int.self) ?? 0
AxisGridLine()
AxisValueLabel(String("\(value)"))
}
}
//.chartScrollableAxes(.horizontal) // future use
Group {
Toggle("Show Steps", isOn: $showSteps)
Toggle("Show Trend", isOn: $showTrend)
}.padding(.horizontal)
}
}
}
enum DataType {
case data
case trend
}
struct DataPoint: Hashable, Identifiable {
var id : UUID = UUID()
var type : DataType
var date : Date
var amount : Double
}
let dataPoints: [DataPoint] = [
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -14), amount: 100),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -13), amount: 97),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -10), amount: 85),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -9), amount: 84),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -8), amount: 82),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -7), amount: 78),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -6), amount: 75),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -5), amount: 68),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -4), amount: 65),
DataPoint(id: UUID(), type: .data, date: Date(timeIntervalSinceNow: 3600 * 24 * -3), amount: 50),
DataPoint(id: UUID(), type: .data, date: Date(), amount: 48),
DataPoint(id: UUID(), type: .trend, date: Date(timeIntervalSinceNow: 3600 * 24 * -15), amount: 100),
DataPoint(id: UUID(), type: .trend, date: Date(timeIntervalSinceNow: 3600 * 24 * 15), amount: 0)
]
解决方案需要使用可滚动图表,因为最终图表将使用很长的时间表.(包含可滚动修饰符,但已被注释)
在线性图上try 了不同的插值方法,将数据分成两个数组,使用图表叠加并使用CGPath创建趋势线.其中之一可能是一个解决方案,但我可能错过了如何正确设置它.
有关于如何使用另一个LineMark正确使用所需趋势线的提示吗?或者如何在不使用LineMark的情况下创建趋势线?