Try to set -ve and +ve value and zero as Ycenter
Please check my code and my graph below. image below
ForEach(0..<stack.count, id: \.self) { index in
if let xValue = stack[index].x ,
let yValue = stack[index].yValues?[0].value,
let hexaString = stack[index].yValues?[0].color {
BarMark(
x: .value("x", "\(xValue)"),
y: .value("y", "\(yValue)")
)
.foregroundStyle(Color(hex: hexaString))
}
}
You are plotting the y axes as categorical data (i.e. strings), which makes all the bars rectangles with the same size.
If the x and y values are numerical, just plot them as numerical data.
BarMark(
x: .value("X", xValue),
y: .value("Y", yValue),
width: 10 // you should specify the width of the bar
)
To fix y=0 at the centre, you can use chartYScale
to modify the range of the y axis.
// dataType should be passed the type of yValue
.chartYScale(domain: .automatic(includesZero: true, dataType: Double.self) { domain in
// find the largest number in magnitude in the inferred domain
if let max = domain.map(abs).max() {
// make sure both the positive and negative of that is in the domain
domain.append(max)
domain.append(-max)
}
})
Here is a full example:
struct Foo: Identifiable {
let id = UUID()
let x: Double
let y: Double
}
// have some positive data
let data = (0..<10).map { x in
Foo(x: Double(x), y: Double.random(in: 0...100))
// and some negative data
} + (10..<20).map { x in
Foo(x: Double(x), y: Double.random(in: -20..<0))
}
// the negative data only goes from -20..<0 to demonstrate that y=0 can be centred
struct ContentView: View {
var body: some View {
Chart(data) { foo in
BarMark(
x: .value("X", foo.x),
y: .value("Y", foo.y),
width: 10
)
.foregroundStyle(foo.y < 0 ? .red : .green)
}
.chartYScale(domain: .automatic(includesZero: true, dataType: Double.self) { domain in
if let max = domain.map(abs).max() {
domain.append(max)
domain.append(-max)
}
})
.frame(height: 500)
.padding()
}
}
Output: