Files
SwiftUI/Examples/Composing Complex Interfaces/StartingPoint/Landmarks/Landmarks/Supporting Views/HikeGraph.swift
2019-06-06 22:24:34 +03:00

75 lines
2.2 KiB
Swift
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
See LICENSE folder for this samples licensing information.
Abstract:
The elevation, heart rate, and pace of a hike plotted on a graph.
*/
import SwiftUI
func rangeOfRanges<C: Collection>(_ ranges: C) -> Range<Double>
where C.Element == Range<Double> {
guard !ranges.isEmpty else { return 0..<0 }
let low = ranges.lazy.map { $0.lowerBound }.min()!
let high = ranges.lazy.map { $0.upperBound }.max()!
return low..<high
}
func magnitude(of range: Range<Double>) -> Double {
return range.upperBound - range.lowerBound
}
struct HikeGraph: View {
var hike: Hike
var path: KeyPath<Hike.Observation, Range<Double>>
var color: Color {
switch path {
case \.elevation:
return .gray
case \.heartRate:
return Color(hue: 0, saturation: 0.5, brightness: 0.7)
case \.pace:
return Color(hue: 0.7, saturation: 0.4, brightness: 0.7)
default:
return .black
}
}
var body: some View {
let data = hike.observations
let overallRange = rangeOfRanges(data.lazy.map { $0[keyPath: self.path] })
let maxMagnitude = data.map { magnitude(of: $0[keyPath: path]) }.max()!
let heightRatio = 1 - Length(maxMagnitude / magnitude(of: overallRange))
return GeometryReader { proxy in
HStack(alignment: .bottom, spacing: proxy.size.width / 120) {
ForEach(data.indices) { index in
GraphCapsule(
index: index,
height: proxy.size.height,
range: data[index][keyPath: self.path],
overallRange: overallRange)
.colorMultiply(self.color)
}
.offset(x: 0, y: proxy.size.height * heightRatio)
}
}
}
}
#if DEBUG
struct HikeGraph_Previews: PreviewProvider {
static var previews: some View {
Group {
HikeGraph(hike: hikeData[0], path: \.elevation)
.frame(height: 200)
HikeGraph(hike: hikeData[0], path: \.heartRate)
.frame(height: 200)
HikeGraph(hike: hikeData[0], path: \.pace)
.frame(height: 200)
}
}
}
#endif