diff --git a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/HikeDetail.swift b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/HikeDetail.swift index c40c2a6..6256bc4 100644 --- a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/HikeDetail.swift +++ b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/HikeDetail.swift @@ -7,9 +7,24 @@ A view showing the details for a hike. import SwiftUI +extension KeyPath where Root == Hike.Observation, Value == Range { + + var superDescription: String { + switch self { + case \.elevation: return ".elevation" + case \.heartRate: return ".heartRate" + case \.pace: return ".pace" + default: return "dunno" + } + } +} + struct HikeDetail: View { let hike: Hike - @State var dataToShow = \Hike.Observation.elevation + @State var dataToShow = \Hike.Observation.elevation { + willSet { print(dataToShow.superDescription) } + didSet { print(dataToShow.superDescription) } + } var buttons = [ ("Elevation", \Hike.Observation.elevation), diff --git a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/SceneDelegate.swift b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/SceneDelegate.swift index a1104cc..77691b0 100644 --- a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/SceneDelegate.swift +++ b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/SceneDelegate.swift @@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // Use a UIHostingController as window root view controller if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) - window.rootViewController = UIHostingController(rootView: LandmarkList().environmentObject(UserData())) + window.rootViewController = UIHostingController(rootView: HikeView(hike: hikeData[0]).environmentObject(UserData())) self.window = window window.makeKeyAndVisible() } diff --git a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/Supporting Views/HikeGraph.swift b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/Supporting Views/HikeGraph.swift index c13213a..fbe9e30 100644 --- a/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/Supporting Views/HikeGraph.swift +++ b/5 Animating Views and Transitions/Complete/Landmarks/Landmarks/Supporting Views/HikeGraph.swift @@ -30,8 +30,15 @@ extension Animation { struct HikeGraph: View { var hike: Hike var path: KeyPath> + + init(hike: Hike, path: KeyPath>) { + self.hike = hike + self.path = path + print(path.superDescription) + } var color: Color { + print(path.superDescription) switch path { case \.elevation: return .gray @@ -43,27 +50,47 @@ struct HikeGraph: View { return .black } } - - var body: some View { + + func graph(proxy: GeometryProxy) -> 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 - CGFloat(maxMagnitude / magnitude(of: overallRange))) / 2 - 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) - .transition(.slide) - .animation(.ripple(index: index)) - } - .offset(x: 0, y: proxy.size.height * heightRatio) + struct Info: Identifiable { + let index: Int + let range: Range + var id: String { "\(index) \(range)" } + } + + let infos = data.enumerated().map { index, observation in + Info(index: index, range: observation[keyPath: self.path]) + } + + func capsule(proxy: GeometryProxy, info: Info) -> some View { + print("CAPSULE", index) + return GraphCapsule( + index: info.index, + height: proxy.size.height, + range: info.range, + overallRange: overallRange) + .colorMultiply(self.color) + .transition(.slide) + .animation(.ripple(index: info.index)) + } + + return HStack(alignment: .bottom, spacing: proxy.size.width / 120) { + ForEach(infos) { info in + capsule(proxy: proxy, info: info) } + .offset(x: 0, y: proxy.size.height * heightRatio) + } + } + + var body: some View { + GeometryReader { proxy in + self.graph(proxy: proxy) } } }