skip to Main Content

I’m trying to add axis unit labels to a chart built with Swift Charts.

For example:

import SwiftUI
import Charts

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 {
        Chart(data) {
            LineMark(
                x: .value("Position", $0.xVal),
                y: .value("Height", $0.yVal)
            )
        }
        .chartYAxis {
            AxisMarks(position: .leading)
        }
    }
    
}

Chart output, with the desired labels annotated in red:
enter image description here

How can we create axis labels like those in red above – or otherwise add units/descriptions to our axes?

Edit: I finally found it, see my answer below.

2

Answers


  1. Chosen as BEST ANSWER

    This is the correct modifier:

    Chart {
        ...
    }
    .chartXAxisLabel("Position (meters)")
    

    You can also provide a custom view like this:

    
    Chart {
        ...
    }
    .chartXAxisLabel(position: .bottom, alignment: .center) {
        Text("Position (meters)")
    }
    

  2. 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:

    enter image description here

    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:
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search