Search code examples
swiftuicharts

I'm trying to understand the swiftUI Charts API specifically overlaying charts and modifying certain aspects of the chart


I just started working with Charts in swiftui and I'm struggling. I'd like to overlay my bar chart in the image below with a line chart. But the only way I can figure out how is to embed in a ZStack, but as shown in the screenshot the two charts(same data passed for now) don't align. I'd like to show maybe an average line overlaying the bars, but I just can't figure it out. I don't know much about charting and I'm new to this API as well. Also I'd like to display the actual amount on the bar or above the bar or something. Not sure if any of this is possible in swiftui yet. If nothing else can you point me to some good documentation or additional info on Charts? Thanks

enter image description here

Here's a simplification of my code

        ZStack {
        Chart {
            ForEach(payments, id: \.date) { payment in

                BarMark(
                    x: .value("Date", payment.date),
                    y: .value("Amount", payment.amount)
                )
            }
        }

        Chart {

            ForEach(payments, id: \.date) { payment in
                LineMark(
                    x: .value("Date", payment.date),
                    y: .value("Amount", payment.amount)
                )
            }
        }
    }

Solution

  • Try this approach where you use one Chart with two ForEach, such as:

     Chart {
         ForEach(payments, id: \.date) { payment in
             BarMark(
                 x: .value("Date", payment.date, unit: .day), // <-- adjust as required
                 y: .value("Amount", payment.amount)
             )
         }
    
         ForEach(payments, id: \.0) { payment in
             LineMark(
                 x: .value("Date", payment.date, unit: .day), // <-- adjust as required
                 y: .value("Amount", payment.amount)
             )
         }
     }
    

    Here is my full test code that shows how to have the BarMark together with the LineMark on top.

    struct ChartData: Identifiable {
        let id = UUID()
        let value: Double
        let date: Date
    }
    
    struct ContentView: View {
        
        let chartData: [ChartData] = (0..<10).map { index in
            ChartData(value: Double.random(in: 1...10) ,
                      date: Date().addingTimeInterval(Double(index) * 60 * 60 * 24) )
        }
    
        var body: some View {
            Chart {
                ForEach(chartData) { data in
                    BarMark(
                        x: .value("Date", data.date, unit: .day),
                        y: .value("Value", data.value)
                    )
                    .foregroundStyle(Color.blue)
                }
                ForEach(chartData) { data in
                    LineMark(
                        x: .value("Date", data.date, unit: .day),
                        y: .value("Value", data.value)
                    )
                    .foregroundStyle(Color.red)
                }
            }
            .chartLegend(.hidden)
            .chartXAxis(.hidden)
            .chartYAxis(.hidden)
        }
    }