changeset 98:b49877856a71

Implement LineView for stock prices
author Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com>
date Sat, 30 Jan 2021 19:43:15 +0100
parents bd35f88e65cd
children 3e92dce4b799
files LazyBear.xcodeproj/project.pbxproj LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate lazybear/Views/Line.swift lazybear/Views/LineView.swift lazybear/Views/Stock.swift
diffstat 5 files changed, 140 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear.xcodeproj/project.pbxproj	Sat Jan 30 19:34:25 2021 +0100
+++ b/LazyBear.xcodeproj/project.pbxproj	Sat Jan 30 19:43:15 2021 +0100
@@ -23,6 +23,8 @@
 		95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */; };
 		95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */; };
 		95AD892425C5D8A200BCE8E4 /* AddWatchlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */; };
+		95AD892725C5DF2400BCE8E4 /* LineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AD892625C5DF2400BCE8E4 /* LineView.swift */; };
+		95AD892A25C5DF5C00BCE8E4 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AD892925C5DF5C00BCE8E4 /* Line.swift */; };
 		95B04EB325212369000AD27F /* LazyBearApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B04EB225212369000AD27F /* LazyBearApp.swift */; };
 		95B04EB525212369000AD27F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B04EB425212369000AD27F /* ContentView.swift */; };
 		95B04EB72521236A000AD27F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95B04EB62521236A000AD27F /* Assets.xcassets */; };
@@ -65,6 +67,8 @@
 		95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyModel.swift; path = lazybear/Models/CompanyModel.swift; sourceTree = SOURCE_ROOT; };
 		95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyRow.swift; sourceTree = "<group>"; };
 		95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AddWatchlist.swift; path = lazybear/Views/AddWatchlist.swift; sourceTree = SOURCE_ROOT; };
+		95AD892625C5DF2400BCE8E4 /* LineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LineView.swift; path = lazybear/Views/LineView.swift; sourceTree = SOURCE_ROOT; };
+		95AD892925C5DF5C00BCE8E4 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Line.swift; path = lazybear/Views/Line.swift; sourceTree = SOURCE_ROOT; };
 		95B04EAF25212369000AD27F /* LazyBear.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LazyBear.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		95B04EB225212369000AD27F /* LazyBearApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyBearApp.swift; sourceTree = "<group>"; };
 		95B04EB425212369000AD27F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@@ -149,6 +153,8 @@
 				95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */,
 				95F6C30425BAF599003CF389 /* CompanyHeader.swift */,
 				95F6C30825BAF7C2003CF389 /* DateSelection.swift */,
+				95AD892625C5DF2400BCE8E4 /* LineView.swift */,
+				95AD892925C5DF5C00BCE8E4 /* Line.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -301,6 +307,7 @@
 				9597CE0125C1DC0A004DDFED /* LogoModifier.swift in Sources */,
 				954DDF0425C456E800848A4B /* QuoteModel.swift in Sources */,
 				9597CE0425C1DFE7004DDFED /* LogoPlaceholder.swift in Sources */,
+				95AD892725C5DF2400BCE8E4 /* LineView.swift in Sources */,
 				95FE646B25C30B880052832E /* ApiModel.swift in Sources */,
 				95F6C30525BAF599003CF389 /* CompanyHeader.swift in Sources */,
 				95612C512598D48200F7698F /* SearchBar.swift in Sources */,
@@ -314,6 +321,7 @@
 				95F6C30925BAF7C2003CF389 /* DateSelection.swift in Sources */,
 				95F6C2F025BAE2ED003CF389 /* Company.swift in Sources */,
 				95F6F46125C20E63002AC66A /* ListHeader.swift in Sources */,
+				95AD892A25C5DF5C00BCE8E4 /* Line.swift in Sources */,
 				95D1BF4925ADCF7700E5D063 /* Persistence.swift in Sources */,
 				958B678525C42B2400BF9F89 /* ApiAccess.swift in Sources */,
 				95E4119225BEC56F00A9C23F /* SuperTitle.swift in Sources */,
Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/Views/Line.swift	Sat Jan 30 19:43:15 2021 +0100
@@ -0,0 +1,76 @@
+//
+//  Line.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 30/1/21.
+//
+
+import SwiftUI
+
+struct Line: View {
+    var data: [(Double)]
+    @Binding var frame: CGRect
+
+    let padding:CGFloat = 30
+    
+    var stepWidth: CGFloat {
+        if data.count < 2 {
+            return 0
+        }
+        return frame.size.width / CGFloat(data.count-1)
+    }
+    var stepHeight: CGFloat {
+        var min: Double?
+        var max: Double?
+        let points = self.data
+        if let minPoint = points.min(), let maxPoint = points.max(), minPoint != maxPoint {
+            min = minPoint
+            max = maxPoint
+        }else {
+            return 0
+        }
+        if let min = min, let max = max, min != max {
+            if (min <= 0){
+                return (frame.size.height-padding) / CGFloat(max - min)
+            }else{
+                return (frame.size.height-padding) / CGFloat(max + min)
+            }
+        }
+        
+        return 0
+    }
+    var path: Path {
+        let points = self.data
+        return Path.lineChart(points: points, step: CGPoint(x: stepWidth, y: stepHeight))
+    }
+    
+    public var body: some View {
+        
+        ZStack {
+
+            self.path
+                .stroke(Color.green ,style: StrokeStyle(lineWidth: 3, lineJoin: .round))
+                .rotationEffect(.degrees(180), anchor: .center)
+                .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
+                .drawingGroup()
+        }
+    }
+}
+
+extension Path {
+    
+    static func lineChart(points:[Double], step:CGPoint) -> Path {
+        var path = Path()
+        if (points.count < 2){
+            return path
+        }
+        guard let offset = points.min() else { return path }
+        let p1 = CGPoint(x: 0, y: CGFloat(points[0]-offset)*step.y)
+        path.move(to: p1)
+        for pointIndex in 1..<points.count {
+            let p2 = CGPoint(x: step.x * CGFloat(pointIndex), y: step.y*CGFloat(points[pointIndex]-offset))
+            path.addLine(to: p2)
+        }
+        return path
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/Views/LineView.swift	Sat Jan 30 19:43:15 2021 +0100
@@ -0,0 +1,55 @@
+//
+//  LineView.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 30/1/21.
+//
+
+import SwiftUI
+
+struct LineView: View {
+    var data: [(Double)]
+    var title: String?
+    var price: String?
+
+    public init(data: [Double],
+                title: String? = nil,
+                price: String? = nil) {
+        
+        self.data = data
+        self.title = title
+        self.price = price
+    }
+    
+    public var body: some View {
+        GeometryReader{ geometry in
+            VStack(alignment: .leading, spacing: 8) {
+                Group{
+                    if (self.title != nil){
+                        Text(self.title!)
+                            .font(.title)
+                    }
+                    if (self.price != nil){
+                        Text(self.price!)
+                            .font(.body)
+                        .offset(x: 5, y: 0)
+                    }
+                }.offset(x: 0, y: 0)
+                ZStack{
+                    GeometryReader{ reader in
+                        Line(data: self.data,
+                             frame: .constant(CGRect(x: 0, y: 0, width: reader.frame(in: .local).width , height: reader.frame(in: .local).height))
+                             
+                        )
+                            .offset(x: 0, y: 0)
+                    }
+                    .frame(width: geometry.frame(in: .local).size.width, height: 200)
+                    .offset(x: 0, y: -100)
+
+                }
+                .frame(width: geometry.frame(in: .local).size.width, height: 200)
+        
+            }
+        }
+    }
+}
--- a/lazybear/Views/Stock.swift	Sat Jan 30 19:34:25 2021 +0100
+++ b/lazybear/Views/Stock.swift	Sat Jan 30 19:43:15 2021 +0100
@@ -32,6 +32,7 @@
             
             Divider()
             DateSelection(selectedperiod: $selectedPeriod)
+            LineView(data: [50, 60, 40, 20, 30, 40, 30])
         }
         .padding([.leading, .trailing])
     }