skip to Main Content

I understood that I have to use the following line but I don’t know how to use it in SwiftUI : chart.xAxis.forceLabelsEnabled = true

Here is my charts :

var sampleData: [Int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Chart {
                    ForEach(sampleData.indices, id: .self) { index in
                        BarMark(x: .value("x", String(Calendar.current.monthSymbols[index].prefix(3))),
                                y: .value("y", index))
                    }
                }
                .chartYAxis(.hidden)
                .frame(height: 180)

With the result :
FirstChart

In french, June = Juin and July = Juillet.

As the first 3 letters of JUIN and JUILLET are the same then the fusion values. One of the solutions is to put .prefix(4) but that’s not what I want

Result in French :
Second Chart

2

Answers


  1. To make this work you need, as noted, to keep the x values unique and therefore we need to build the label for the x axis separately using .chartXAxis

    First change the BarMark to use the index as the x value

    BarMark(x: .value("x", "(index)"),
            y: .value("y", index))
    

    We need to make it a string to match the type we will be using below as the label data.

    Then add a new modifier to Chart

    .chartXAxis() {
        AxisMarks { value in
            let month = Calendar.current.monthSymbols[value.index]
            AxisValueLabel { Text(String(month.prefix(3))) }
        }
    }
    
    Login or Signup to reply.
  2. You should not give your data duplicate X values in the first place. Since your data is date-based, actually create some Dates. For example:

    ForEach(sampleData.indices, id: .self) { index in
        // in reality your data source should this information from your data,
        // instead creating Dates ad hoc like this
        BarMark(x: .value("x", Calendar.current.date(from: .init(month: index + 1))!),
                y: .value("y", index))
    }
    

    Then, if you want to format some of them to the same strings, that is totally possible:

    .chartXAxis {
        AxisMarks(preset: .aligned, values: .stride(by: .month)) { value in
            AxisValueLabel(monthNames[value.index])
        }
    }
    

    where monthNames is an array, e.g.

    let monthNames = {
        var calendar = Calendar.current
        // My locale isn't French, so I hardcoded the locale in
        calendar.locale = Locale(identifier: "fr")
        return calendar.monthSymbols.map { String($0.prefix(3)) }
    }()
    

    That said, I would recommend using the built-in date formats:

    .chartXAxis {
        let format = Date.FormatStyle(locale: .init(identifier: "fr")).month(.abbreviated)
        AxisMarks(format: format, preset: .aligned, values: AxisMarkValues.stride(by: .month))
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search