0

I have a chart with a line:

let ints = Array([0...10])
Chart {
    ForEach(ints) { int in
        let someRandomYValue = Int.random()
        LineMark(x: int, y: someRandomYValue)
    }
}

At the halfway point across the chart, I need an annotation all the ay at the top. The annotation should be some text with a line that comes out of the bottom of the annotation and stops at the chart line. Something like the blue in this image: enter image description here

Any thoughts on how to tackle this?

swiftyboi
  • 2,965
  • 4
  • 25
  • 52

1 Answers1

0

You cannot use .annotation because you need the average values between two points. But you can use .chartOverlay, which gives you a proxy you can query for those values.

enter image description here

struct ContentView: View {

    let data: [(Int, Int)] = {
        (0...15).map { ($0, Int.random(in: 0...50)) }
    }()

    @State private var selectedX = 6
    
    var body: some View {
        
        VStack {
            Chart {
                ForEach(data.indices, id: \.self) { i in
                    let (x,y) = data[i]
                    LineMark(
                        x: .value("x", x),
                        y: .value("y", y)
                    )
                }
            }
            .frame(height: 300)
            .chartOverlay { proxy in
                
                let pos1 = proxy.position(for: (x: selectedX, y: data[selectedX].1)) ?? .zero
                let pos2 = proxy.position(for: (x: selectedX+1, y: data[selectedX+1].1)) ?? .zero
                let lineHeight = (pos1.y + pos2.y) / 2.0 - 24
                
                VStack(spacing: 0) {
                    Text("x: \(selectedX), y: \(data[selectedX].1)")
                        .padding()
                        .background(.gray.opacity(0.5))
                    Color.gray
                        .frame(width: 1, height: lineHeight)
                }
                .position(x: (pos1.x + pos2.x)/2, y: lineHeight / 2 )
            }
         
            Stepper("", value: $selectedX, in: 0...data.count-2)
            
        }
        .padding()
    }
}
ChrisR
  • 9,523
  • 1
  • 8
  • 26