a .stride solution based on Olivers suggestion:
func myChart() -> some View {
var yAxisMaxValue = 23532 //get the min and max values from your data
var yAxisMinValue = -7633 //get the min and max values from your data
let roundedYAxisMaxValue = roundUp(yAxisMaxValue, to: 2)
let roundedYAxisMinValue = roundUp(yAxisMinValue, to: 2)
let strideValue = max(abs(roundedYAxisMaxValue), abs(roundedYAxisMinValue)) / 3.0 //max 3 axis marks above and max 3 below zero
return Chart {
//your chart layout code
}
.chartYAxis {
AxisMarks(values: .stride(by: strideValue)) {
let value = $0.as(Double.self)!
AxisGridLine()
AxisTick()
AxisValueLabel {
Text("\(self.abbreviateAxisValue(string: "\(value)"))")
}
}
}
}
func abbreviateAxisValue(string: String) -> String {
let decimal = Decimal(string: string)
if decimal == nil {
return string
} else {
if abs(decimal!) > 1000000000000.0 {
return "\(decimal! / 1000000000000.0)t"
} else if abs(decimal!) > 1000000000.0 {
return "\(decimal! / 1000000000.0)b"
} else if abs(decimal!) > 1000000.0 {
return "\(decimal! / 1000000.0)m"
} else if abs(decimal!) > 1000.0 {
return "\(decimal! / 1000.0)k"
} else {
return "\(decimal!)"
}
}
}
//round up to x significant digits
func roundUp(_ num: Double, to places: Int) -> Double {
let p = log10(abs(num))
let f = pow(10, p.rounded(.up) - Double(places) + 1)
let rnum = (num / f).rounded(.up) * f
return rnum
}