One way to create those red labels is to use a combination of Text with VStack or HStack as needed. The text can be rotated using rotationEffect(). This is the original code with modifications:
struct ContentView: View {
struct ChartData: Identifiable {
var id: Double { xVal }
let xVal: Double
let yVal: Double
}
let data: [ChartData] = [
.init(xVal: -5, yVal: 5),
.init(xVal: 0, yVal: 10),
.init(xVal: 5, yVal: 20),
]
var body: some View {
HStack(alignment: .center, spacing: 0) {
Text("Height(cm)")
.rotationEffect(Angle(degrees: -90))
.foregroundColor(.red)
VStack {
Chart(data) {
LineMark(
x: .value("Position", $0.xVal),
y: .value("Height", $0.yVal)
)
}
.chartYAxis {
AxisMarks(position: .leading)
}
Text("Position(meters)")
.foregroundColor(.red)
}
}
.frame(width: 350, height: 400, alignment: .center)
}
}
This is the resulting layout:
Use AxisMarks() to change the default axis marks including labels, grid lines and tick marks. Within AxisMarks individual axis labels can be assigned using AxisValueLabel(). Text() is formatted as an individual label for AxisValueLabel()'s content.
When AxisMarks is used, the default grid lines and tick marks disappear, so they have been added back using AxisGridLine() and AxisTick(). The following code should be added immediately following Chart{} and replacing the original .chartYAxis():
.chartXAxis {
AxisMarks(position: .bottom, values: .automatic) { value in
AxisGridLine(centered: true, stroke: StrokeStyle(dash: [1, 2]))
AxisTick(centered: true, stroke: StrokeStyle(dash: [1, 2]))
AxisValueLabel() {
if let intValue = value.as(Int.self) {
Text("\(intValue) m")
.font(.system(size: 10))
}
}
}
}
.chartYAxis {
AxisMarks(position: .leading, values: .automatic) { value in
AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1))
AxisValueLabel() {
if let intValue = value.as(Int.self) {
Text("\(intValue) cm")
.font(.system(size: 10))
}
}
}
}
The chart with custom labels will look like this: