Guest User

Untitled

a guest
May 29th, 2021
557
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.01 KB | None | 0 0
  1. import SwiftUI
  2. import WidgetKit
  3.  
  4. struct LineGraph: Shape {
  5.  
  6. var pricePoints: [CGFloat]
  7.  
  8. func path(in rect: CGRect) -> Path {
  9. var normalizedPrices = pricePoints.normalized
  10.  
  11. if normalizedPrices.isEmpty {
  12. normalizedPrices = [0,1]
  13. }
  14.  
  15. func point(at index: Int) -> CGPoint {
  16. let point = normalizedPrices[index]
  17. let x = rect.width * CGFloat(index) / CGFloat(normalizedPrices.count - 1)
  18. let y = (1 - point) * rect.height
  19. return CGPoint(x: x, y: y)
  20. }
  21.  
  22. return Path { path in
  23. path.move(to: .zero)
  24. guard normalizedPrices.count > 1 else { return }
  25. let start = normalizedPrices[0]
  26. path.move(to: CGPoint(x: 0, y: (1 - start) * rect.height))
  27.  
  28. for index in normalizedPrices.indices {
  29. path.addLine(to: point(at: index))
  30. }
  31.  
  32. path.addLine(to: CGPoint(x: 1.1 * rect.width, y: rect.height * 1.5))
  33. path.addLine(to: CGPoint(x: -1.1 * rect.width , y: rect.height * 1.5))
  34. path.move(to: CGPoint(x: -1.1, y: (1 - start) * rect.height))
  35. path.closeSubpath()
  36. }
  37. }
  38. }
  39.  
  40. struct OpeningPrice: Shape {
  41.  
  42. var pricePoints: [CGFloat]
  43. var openingPrice: CGFloat
  44.  
  45. func path(in rect: CGRect) -> Path {
  46.  
  47. var prices = pricePoints
  48. prices.append(openingPrice)
  49. let normalized = prices.normalized
  50.  
  51. return Path { path in
  52. path.move(to: .zero)
  53. guard normalized.count > 1 else { return }
  54. let start = normalized[normalized.count - 1]
  55. path.move(to: CGPoint(x: 0, y: (1 - start) * rect.height))
  56.  
  57. path.addLine(to: CGPoint(x: 1 * rect.width, y: (1 - start) * rect.height))
  58.  
  59. }
  60. }
  61. }
  62.  
  63.  
  64. struct ChartView: View {
  65. let dailyChange: Double
  66. var pricePoints: [CGFloat]
  67. let openingPrice: CGFloat
  68. let fillOpacity: Double
  69.  
  70. @State var tempPoints: [CGFloat] = []
  71. @State var showShimmering = false
  72.  
  73. var body: some View {
  74. ZStack {
  75.  
  76. ZStack {
  77. LineGraph(pricePoints: pricePoints.isEmpty ? tempPoints : pricePoints)
  78. .fill(LinearGradient(gradient: Gradient(colors: [dailyChange.getPriceChangeColor().opacity(pricePoints.isEmpty ? 0.4 : fillOpacity), Color.clear]), startPoint: .top, endPoint: .bottom))
  79. .clipped()
  80.  
  81. if pricePoints.isEmpty {
  82. LineGraph(pricePoints: pricePoints.isEmpty ? tempPoints : pricePoints)
  83. .fill(LinearGradient(gradient: Gradient(colors: [dailyChange.getPriceChangeColor().opacity(fillOpacity), Color.clear]), startPoint: .top, endPoint: .bottom))
  84. .clipped()
  85. .mask(
  86. Capsule()
  87. .fill(LinearGradient(gradient: .init(colors: [.clear, .newsColor, .clear]), startPoint: .top, endPoint: .bottom))
  88. .rotationEffect(.init(degrees: 30))
  89. .offset(x: showShimmering ? 360 : -360)
  90. )
  91. .onAppear {
  92. withAnimation(Animation.default.speed(0.15).delay(0).repeatForever(autoreverses: false)) {
  93. showShimmering.toggle()
  94. }
  95. }
  96. }
  97. }
  98.  
  99. OpeningPrice(pricePoints: pricePoints.isEmpty ? tempPoints : pricePoints, openingPrice: openingPrice)
  100. .stroke(style: StrokeStyle( lineWidth: 1, dash: [4]))
  101. .foregroundColor(dailyChange.getPriceChangeColor())
  102. .clipped()
  103. .opacity(pricePoints.isEmpty ? 0 : 1)
  104.  
  105. LineGraph(pricePoints: pricePoints.isEmpty ? tempPoints : pricePoints)
  106. .stroke(dailyChange.getPriceChangeColor(), style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round))
  107. .clipped()
  108. }
  109. .onAppear(perform: {
  110. if pricePoints.isEmpty {
  111. tempPoints = getRandomPoints()
  112. }
  113. })
  114. }
  115.  
  116. func getRandomPoints() -> [CGFloat] {
  117. var pointsArray: [CGFloat] = []
  118. var previousValue = CGFloat.random(in: 0.1...0.9)
  119.  
  120. for _ in (0...75) {
  121. previousValue = CGFloat.random(in: max(0.1, (previousValue - 0.01))...min((previousValue + 0.01), 0.9))
  122. pointsArray.append(previousValue)
  123. }
  124.  
  125. return pointsArray
  126. }
  127. }
  128.  
  129. extension Double {
  130. func getPriceChangeColor() -> Color {
  131. let roundedDouble = self.roundTo(places: 2)
  132. if roundedDouble > 0 {
  133. return Color.mainGreen
  134. } else if roundedDouble < 0 {
  135. return Color.mainRed
  136. } else {
  137. return Color.mainGray
  138. }
  139. }
  140. }
Advertisement
Add Comment
Please, Sign In to add comment