81 lines
2.2 KiB
Swift
81 lines
2.2 KiB
Swift
import SwiftUI
|
|
import Charts
|
|
|
|
struct HeartRateGraph: View {
|
|
|
|
let measurements: [HRSample]
|
|
|
|
let width: CGFloat
|
|
|
|
init(measurements: [HRSample], width: CGFloat = 5.0) {
|
|
self.measurements = measurements
|
|
self.width = width
|
|
self.maximumValue = measurements.map { $0.max }.max() ?? 100
|
|
self.minimumValue = measurements.map { $0.min }.min() ?? 80
|
|
}
|
|
|
|
private let maximumValue: Int
|
|
|
|
private let minimumValue: Int
|
|
|
|
var range: ClosedRange<Int> {
|
|
(minimumValue-10)...(maximumValue+10)
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
Chart(measurements, id: \.id) {
|
|
BarMark(x: .value("Time Start", $0.startDate),
|
|
yStart: .value("BPM Min", $0.min - 1),
|
|
yEnd: .value("BPM Max", $0.max + 1),
|
|
width: .inset(1))
|
|
.clipShape(Capsule())
|
|
.foregroundStyle(.red)
|
|
}
|
|
.chartYScale(domain: range)
|
|
.chartXAxis {
|
|
AxisMarks {
|
|
AxisValueLabel()
|
|
AxisGridLine(stroke: .init())
|
|
}
|
|
}
|
|
.chartYAxis {
|
|
AxisMarks {
|
|
AxisValueLabel()
|
|
}
|
|
}
|
|
.chartYAxis(.hidden)
|
|
HStack {
|
|
Spacer()
|
|
VStack(alignment: .trailing) {
|
|
Text("\(maximumValue)")
|
|
Spacer()
|
|
Text("\(minimumValue)")
|
|
}
|
|
.foregroundStyle(Color.primary.opacity(0.8))
|
|
.font(.caption)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
let now = Date.now
|
|
let count = 50
|
|
let interval = TimeInterval(600)
|
|
let samples = (0..<count).map {
|
|
let start = now.addingTimeInterval(TimeInterval($0) * interval)
|
|
return HRSample(date: start,
|
|
duration: interval,
|
|
min: ($0 * 5) % 100 + 50,
|
|
max: ($0 * 5) % 100 + 70)
|
|
}
|
|
return HeartRateGraph(measurements: samples)
|
|
.padding(5)
|
|
.background(Color.gray.opacity(0.7))
|
|
.clipShape(RoundedRectangle(cornerSize: .init(width: 8, height: 8)))
|
|
.frame(height: 120)
|
|
.padding()
|
|
|
|
}
|