Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Charts: .chartYScale only seems to work with increments of 100?

Given this is a heart rate chart, I'm trying to make the chart's Y max scale 210 (bpm), e.g. .chartYScale(domain: 0 ... 210) however it only seems to scale correctly if I pass in 200 or 300, anything in between doesn't work. Is this intended or a bug?

import SwiftUI
import Charts
import HealthKit

struct TestYAxisRangeChart: View {
    
    let heartRateData = [80.0, 90.0, 120.0, 150.0, 160.0, 140.0, 125.0, 110.0, 88.0]
    
    var body: some View {
        Chart {
            ForEach(heartRateData, id: \.self) { sample in
                LineMark(
                    x: .value("", heartRateData.firstIndex(of: sample)!),
                    y: .value("HR", sample))
                .foregroundStyle(Color.red)
                
            }

        }
        .chartYAxis{
            AxisMarks(position: .leading)
        }
        .frame(height: 300)
        .padding(.horizontal)
        .chartYScale(domain: 0 ... 210)
    }
    
}

struct TestYAxisRangeChart_Previews: PreviewProvider {
    static var previews: some View {
        TestYAxisRangeChart()
    }
}
like image 546
GarySabo Avatar asked Aug 31 '25 16:08

GarySabo


2 Answers

Maybe you just need this (Xcode 14b4 / iOS 16):

let yValues = stride(from: 0, to: 220, by: 10).map { $0 } // << here !!

var body: some View {
    Chart {
        ForEach(heartRateData, id: \.self) { sample in
            LineMark(
                x: .value("", heartRateData.firstIndex(of: sample)!),
                y: .value("HR", sample))
            .foregroundStyle(Color.red)
            
        }

    }
    .chartYAxis{
        AxisMarks(position: .leading, values: yValues)  // << here !!
    }

demo

Test module on GitHub

like image 88
Asperi Avatar answered Sep 04 '25 22:09

Asperi


chartYScale can be passed an automatic domain excluding 0 if you just want to have the scale not start with 0 (e.g. .chartYScale(domain: .automatic(includesZero: false))), but depending on your data and the computed y stride, 0 may still be visible. To include 210 without setting an explicit domain or values, you could always just plot an invisible point mark at 210, but this will lead to a rounded max y axis value (e.g 250-300 depending on your data). The only way to make the max exactly 210 is taking full control of the axis via values or domain as suggested by others.

like image 44
0xWood Avatar answered Sep 04 '25 20:09

0xWood