GarySabo
GarySabo

Reputation: 6700

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

Upvotes: 4

Views: 4814

Answers (3)

0xWood
0xWood

Reputation: 1534

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.

Upvotes: 5

Chris Paveglio
Chris Paveglio

Reputation: 527

Use range instead of domain, and plotDimension uses the data range automatically, IIRC:

.chartYScale(range: .plotDimension(padding: 20))

Upvotes: -2

Asperi
Asperi

Reputation: 258137

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

Upvotes: 8

Related Questions