Inder_iOS
Inder_iOS

Reputation: 1656

BarMark Chart with +ve and -ve value in SwiftUI

Try to set -ve and +ve value and zero as Ycenter

Please check my code and my graph below. image below this is my graph

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))
         }
       }

but i want this type of graph see below I need this type of graph

Upvotes: 0

Views: 115

Answers (1)

Sweeper
Sweeper

Reputation: 273540

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:

enter image description here

Upvotes: 1

Related Questions