swiftswiftuibar-charthorizontal-scrolling

How to Display Exactly 7 Bars at Once in SwiftUI Chart?


I'm working with SwiftUI's Chart and I want to display exactly 7 bars at once on the screen. Currently, with the following code snippet, I'm only able to see 3 bars at a time on my iPhone 11, and I want to adjust this so that 7 bars are visible simultaneously.

Here is my current implementation:

Chart(somethings, id: \.id) { something in
    BarMark(
        x: .value("Shape Type", something.tag.date, unit: .day),
        y: .value("Total Count", something.tag.duration)
    )
    .foregroundStyle(by: .value("Tag", something.tag))
}
.chartScrollableAxes(.horizontal)

I suspect that the issue might be related to the chart's horizontal scroll behavior or the way the bars are being rendered. How can I adjust my code to ensure that exactly 7 bars are shown at once without needing to scroll?

Any help or suggestions would be greatly appreciated!


Solution

  • chartXVisibleDomain is the modifier that you need.

    For categorical data (i.e. if the x values are strings), you just need to pass in 7 to mean "7 bars at a time".

    However, you seem to have Dates as the x values. In that case, 7 means "7 seconds at a time". Since each bar represents one day, you need to pass 86400 * 7.

    Here is a complete example:

    struct ChartData: Identifiable {
        let date: Date
        let duration: TimeInterval
        
        var id: Date { date }
    }
    
    let data = [
        ChartData(date: .now, duration: 1),
        ChartData(date: .now.addingTimeInterval(86400 * 1), duration: 1),
        ChartData(date: .now.addingTimeInterval(86400 * 2), duration: 2),
        ChartData(date: .now.addingTimeInterval(86400 * 3), duration: 3),
        ChartData(date: .now.addingTimeInterval(86400 * 4), duration: 4),
        ChartData(date: .now.addingTimeInterval(86400 * 5), duration: 5),
        ChartData(date: .now.addingTimeInterval(86400 * 6), duration: 6),
        ChartData(date: .now.addingTimeInterval(86400 * 7), duration: 7),
        ChartData(date: .now.addingTimeInterval(86400 * 8), duration: 8),
        ChartData(date: .now.addingTimeInterval(86400 * 9), duration: 9),
        ChartData(date: .now.addingTimeInterval(86400 * 10), duration: 10),
    ]
    
    struct ContentView: View {
        
        var body: some View {
            Chart(data) { x in
                BarMark(
                    x: .value("X", x.date, unit: .day),
                    y: .value("Y", x.duration)
                )
            }
            .chartScrollableAxes(.horizontal)
            .chartXVisibleDomain(length: 7 * 86400)
        }
    }