I am trying to format the x axis labels using the AxisMarks(values: .automatic) modifier which is not centering the labels. I tried using stride(by: .year) which works but the year values are truncated which is expected due to the number of bars on the x-axis. Is there a better way using AxisMarks(values: .automatic)/or other means to center the labels on the x-axis. Below is my code. Any help/direction is very much appreciated.
struct ContentView: View {
let dateValues: [DateValue] = [
// DateValue(date: Calendar.current.date(from: DateComponents(year: 2010, month: 12, day: 31))!, value: 1250),
// DateValue(date: Calendar.current.date(from: DateComponents(year: 2011, month: 12, day: 31))!, value: 1600),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2012, month: 12, day: 31))!, value: 1750),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2013, month: 12, day: 31))!, value: 1900),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2014, month: 12, day: 31))!, value: 1800),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2015, month: 12, day: 31))!, value: 1700),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2016, month: 12, day: 31))!, value: 2000),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2017, month: 12, day: 31))!, value: 2100),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2018, month: 12, day: 31))!, value: 2000),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2019, month: 12, day: 31))!, value: 2250),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2020, month: 12, day: 31))!, value: 2225),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2021, month: 12, day: 31))!, value: 2300),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2022, month: 12, day: 31))!, value: 2500),
DateValue(date: Calendar.current.date(from: DateComponents(year: 2023, month: 12, day: 31))!, value: 2600),
]
var body: some View {
Chart {
ForEach(dateValues, id:\.date) { point in
BarMark(
x: .value("Date", point.date, unit: .year),
y: .value("Value", point.value))
.annotation(alignment: .center) {
Text(abs(point.value) >= 1e-03 ? String(format: "%.1f", point.value) : "")
.font(.caption2)
.rotationEffect(.degrees(-90))
.frame(width: 70)
}
.cornerRadius(5)
}
}
.chartXAxis {
AxisMarks(values: .automatic/*.stride(by: .year)*/) { year in
AxisTick()
AxisGridLine()
AxisValueLabel(format: .dateTime.year(), centered: true)
}
}
}
}
struct DateValue {
var date: Date
var value: Double
}
You can use collisionResolution
for the axis labels, e.g. like this:
AxisValueLabel(format: .dateTime.year(), centered: true, collisionResolution: .greedy)