Trying to implement a chart into my app where it tracks your profit of a game over time. The idea is very simple, a line chart that shows your progress over the course of a year. I’m using dummy data for now while I style the chart, with dates in Jan, Feb, March, May, and December but for some reason the chart is skewing oddly because the data points are not spaced evenly across the X axis.
Does anyone know how I can fix this?
Code with dummy data below, as well as the image:
let dummyData: [dummySession] = [
.init(date: Date.from(year: 2023, month: 1, day: 1), profit: 0),
.init(date: Date.from(year: 2023, month: 2, day: 12), profit: 55),
.init(date: Date.from(year: 2023, month: 3, day: 20), profit: 376),
.init(date: Date.from(year: 2023, month: 5, day: 2), profit: 120),
.init(date: Date.from(year: 2023, month: 5, day: 18), profit: 500),
.init(date: Date.from(year: 2023, month: 12, day: 11), profit: 222)
]
VStack {
Chart {
ForEach(dummyData) { session in
LineMark(x: .value("Date", session.date, unit: .month),
y: .value("Profit", session.profit))
.lineStyle(.init(lineWidth: 3, lineCap: .round, lineJoin: .round))
}
.interpolationMethod(.cardinal)
}
.chartXAxis {
AxisMarks(stroke: StrokeStyle(lineWidth: 0))
}
.chartYAxis {
AxisMarks(position: .trailing, values: .automatic) { value in
AxisGridLine()
AxisValueLabel() {
if let intValue = value.as(Int.self) {
Text(intValue.asCurrency())
.padding(.leading, 25)
}
}
}
}
}
.frame(maxHeight: 300)
2
Answers
Correct scaling (ignore X Labels)
Instead of using
Date
, you should create your ownPlottable
type that acts like aString
(i.e.primitivePlottable
returns aString
). SwiftData treats strings as categorical data, and plots them with equal spacing.The
DummySession
struct would then be declared as:When creating the chart, you should format the X axis labels in your desired format:
Output: