I already have a working app, using SwiftUI Canvas, for charting sensor milliVolt data at a frequency of 130Hz, so thought I'd see how SwiftUI Charts compared for ease of implementation. Charts is much easier to implement, saving the tedium of scaling and label context placement. However, creating the AxisMarks.Values was a problem because the stride-by method with Calendar.Component has .second as the smallest unit, and I need deciSecond. I tried some other inbuillt options, e.g. desiredCount, but no joy.
After a while I realised that I can create my own values array using a function, so here it is (hoping that this helps someone, somewhere, sometime):
struct ChartView: View {
var chartData : [DataPoint] // An array of CoreData objects with timeStamp and milliVolt attributes
let xSecStyle = StrokeStyle(lineWidth: 1.0)
let xDeciSecStyle = StrokeStyle(lineWidth: 0.5)
...
// The .chartAxis code within Chart in body
.chartXAxis {
AxisMarks(values: deciSecValues) { value in
if Double(value.index).remainder(dividingBy: 10.0) == 0.0 {
// show the second-gridline as wider and display the time label
AxisGridLine(stroke:xSecStyle)
.foregroundStyle(.orange)
AxisValueLabel(format: .dateTime.minute().second(),centered: false)
} else {
AxisGridLine(stroke:xDeciSecStyle)
.foregroundStyle(.orange)
}
}
}
.....
// The func for creating the X Axis Marks
private var deciSecValues : [Date] {
var xDates = [Date]()
if chartData.isEmpty { return xDates }
let deciSecs = (Int(chartData.last!.timeStamp!.timeIntervalSince(chartData.first!.timeStamp!)) + 1) * 10
for i in stride(from: 0, to: deciSecs, by: 1) {
let newTime = Double(i) / 10.0
xDates.append(chartData.first!.timeStamp!.addingTimeInterval(newTime))
}
return xDates
}
Regards, Michaela