skip to Main Content

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

3

Answers


  1. 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

    Login or Signup to reply.
  2. Use range instead of domain, and plotDimension uses the data range automatically, IIRC:

    .chartYScale(range: .plotDimension(padding: 20))
    
    Login or Signup to reply.
  3. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search