So I have a chart displaying line data at equal x intervals, with varying y values - something like this:
let ints = Array([0...10])
Chart {
ForEach(ints) { int in
let someRandomYValue = Int.random()
LineMark(x: int, y: someRandomYValue, series: "Line")
}
}
And I need to put an overlay exactly in the middle of two consecutive points. The overlay needs to touch the line.
So I need the x and the y value to place the overlay.
It's easy enough to get the x value - I just need to split the difference between my two x values. But I can't figure out how to get the y value.
Is there any way to "query" the y value of a line mark at specified x value? Maybe something like this:
let queriedY = LineMark(series: "Line").yValue(at: 8.5)
You can use .chartOverlay
which gives you a chartProxy
that can be queried for the position of chart values.
Here is an example:
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
Text("x: \(selectedX), y: \(data[selectedX].1)")
.padding()
.background(.gray.opacity(0.5))
.position(x: (pos1.x + pos2.x)/2 , y: (pos1.y+pos2.y)/2)
}
Stepper("", value: $selectedX, in: 0...data.count-1)
}
.padding()
}
}