skip to Main Content

Using Swift Charts, I have a bar chart that has dates on the x-axis and points on the y-axis.
This data comes from the property chartData which contains the integer points for each date.
The data point representing today’s date and points could be anywhere in the chartData.

So, I’d like to change the color of the x-axis label to blue for the date that matches today’s date. All other dates should remain in their default color. This gives the user a visual indication of which date is today’s date.

I know how to change the color of all x-axis labels, but this is not what I want. I want to change the color of the one x-axis label that matches todays date. Thank you!

struct DailyPointsChart: View {
    @Binding var scrollPosition: Date
    let chartData: [(Date, Int)]
    
    var body: some View {
        Chart {
            ForEach(chartData, id: .0) { data in
                BarMark(
                    x: .value("Day", data.0, unit: .day),
                    y: .value("Points", data.1)
                )
            }
            .cornerRadius(10)
            .foregroundStyle(Color(UIColor.purple))

        }
        .chartScrollableAxes(.horizontal)
        .chartXVisibleDomain(length: 3600 * 24 * 7) // 7 visible days on chart
        .chartScrollPosition(x: $scrollPosition)
        
        .chartXAxis {
            AxisMarks(values: .stride(by: .day, count: 1)) {
                AxisTick()
                AxisValueLabel(format: .dateTime.month().day())
                    .foregroundStyle(Color.blue) // This changes the color of all x-axis labels, which is not what we want
            }
        }
    }
}


2

Answers


  1. Chosen as BEST ANSWER

    This solution works best, for my project:

    .chartXAxis {
        AxisMarks(values: .stride(by: .day, count: 1)) { value in
              AxisTick()
              AxisValueLabel(format: .dateTime.month().day())
                  .foregroundStyle(value.as(Date.self)?.isSameDay(as: todayDate) ?? false ? Color.blue : .secondary)
        }
    }
    
    extension Date {
        func isSameDay(as otherDate: Date) -> Bool {
            let calendar = Calendar.current
            return calendar.isDate(self, inSameDayAs: otherDate)
        }
    }
    

  2. Try this approach where you specify a particular time value for the AxisMarks, as shown
    in the example code (adjust as required)

    .chartXAxis {
        // the chosen specific time to turn blue
        let chosen = chartData[3].0 // <-- for example
        
        // all except the chosen one
        AxisMarks(values: chartData.filter{$0.0 != chosen}.map{$0.0}) {
            AxisTick()
            AxisValueLabel(format: .dateTime.month().day())
                .foregroundStyle(Color.black)
        }
    
        // just the chosen one
        AxisMarks(values: [chosen]) {
            AxisTick()
            AxisValueLabel(format: .dateTime.month().day())
                .foregroundStyle(Color.blue)
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search