SwiftUI Charts - no chart displayed

151 Views Asked by At

in a more complex chart that displays multiple charts I want to add text annotations to the maximum and minimum value with the value for clarity. To make the annotations easy to read, I want to add a background and a border. When I started working with the annotations, the chart disappeared.

Eventually I discovered a few bugs or ugly features in Charts. The problem is in the .overlay position of the annotations. When the annotation is just Text(), everything is OK and the chart is displayed. When you append .background to the Text() annotation at the .overlay position, the chart does not display.

.annotation(position: .overlay, alignment: .center) {
                    Text("\(hour.value)°")
                        .background(.yellow)
}

Full example:

struct ContentView: View {
    
    struct Value: Identifiable {
        var id = UUID()
        var time: Date
        var value: Int
        
        var timeStr : String {
            "\(time)"
        }
    }
    
    let data = [
        Value(time: Date().startOfHour().adding(hours: 0), value: 7),
        Value(time: Date().startOfHour().adding(hours: 1), value: 9),
        Value(time: Date().startOfHour().adding(hours: 2), value: 12),
        Value(time: Date().startOfHour().adding(hours: 3), value: 16),
        Value(time: Date().startOfHour().adding(hours: 4), value: 6),
    ]
    
    var body: some View {
        
        Chart (data) { hour in
            LineMark(x: .value("Day", hour.time), y: .value("Value", hour.value))
                .interpolationMethod(.catmullRom)
            PointMark(x: .value("Day", hour.time), y: .value("Value", hour.value))
                // step 1: change .top to .overlay and the graph disappears
                .annotation(position: .top, alignment: .center) {
                    Text("\(hour.value)°")
                    // step 2: comment out all text attributes and the graph will reappear
                        .font(.caption2)
                        .padding(.horizontal, 3)
                        .background(
                            RoundedRectangle(cornerRadius: 4).fill(Color.blue.opacity(0.2))
                           )
                        .overlay(
                                RoundedRectangle(cornerRadius: 4)
                                    .stroke(.blue, lineWidth: 1)
                            )
                    // step 2 end
                }
        }
        .padding()
        .frame(height: 200)
    }

    
}

extension Date {
    func startOfHour() -> Date {
        let calendar = Calendar.current
        
        var components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: self)
        
        components.minute = 0
        components.second = 0
        
        return calendar.date(from: components)!
    }
    
    func adding(hours: Int) -> Date {
        Calendar.current.date(byAdding: .hour, value: hours, to: self)!
    }

 }

0

There are 0 best solutions below