TrendShape.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import SwiftUI
  2. struct Triangle: Shape {
  3. /// Flag to be able to adjust size based on Apple Watch size
  4. let isSmallDevice: Bool
  5. /// Creates a triangle shape pointing to the right
  6. func path(in rect: CGRect) -> Path {
  7. var path = Path()
  8. // Draw the triangle pointing to the right
  9. path.move(to: CGPoint(x: rect.maxX - (isSmallDevice ? 7.5 : 9), y: rect.midY))
  10. path.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
  11. path.addQuadCurve(
  12. to: CGPoint(x: rect.minX, y: rect.maxY),
  13. control: CGPoint(x: rect.midX - (isSmallDevice ? 5 : 7), y: rect.midY)
  14. )
  15. path.closeSubpath()
  16. return path
  17. }
  18. }
  19. /// A view that displays a circular trend indicator with a directional triangle
  20. struct TrendShape: View {
  21. /// Rotation angle in degrees for the trend direction
  22. let rotationDegrees: Double
  23. /// Flag to be able to adjust size based on Apple Watch size
  24. let isSmallDevice: Bool
  25. // Angular gradient for the outer circle, transitioning through various blues and purples
  26. private let angularGradient = AngularGradient(
  27. colors: [
  28. Color(red: 0.7215686275, green: 0.3411764706, blue: 1), // #B857FF
  29. Color(red: 0.6235294118, green: 0.4235294118, blue: 0.9803921569), // #9F6CFA
  30. Color(red: 0.4862745098, green: 0.5450980392, blue: 0.9529411765), // #7C8BF3
  31. Color(red: 0.3411764706, green: 0.6666666667, blue: 0.9254901961), // #57AAEC
  32. Color(red: 0.262745098, green: 0.7333333333, blue: 0.9137254902), // #43BBE9
  33. Color(red: 0.7215686275, green: 0.3411764706, blue: 1) // #B857FF (repeated for seamless transition)
  34. ],
  35. center: .center,
  36. startAngle: .degrees(270),
  37. endAngle: .degrees(-90)
  38. )
  39. // Color for the direction indicator triangle
  40. private let triangleColor = Color(red: 0.262745098, green: 0.7333333333, blue: 0.9137254902) // #43BBE9
  41. var body: some View {
  42. let strokeWidth: CGFloat = isSmallDevice ? 4 : 5
  43. let circleSize: CGFloat = isSmallDevice ? 74 : 92
  44. let triangleSize: CGFloat = isSmallDevice ? 16 : 20
  45. let offset: CGFloat = isSmallDevice ? 47.5 : 59
  46. ZStack {
  47. // Outer circle with gradient
  48. Circle()
  49. .stroke(angularGradient, lineWidth: strokeWidth)
  50. .frame(width: circleSize, height: circleSize)
  51. .background(Circle().fill(Color.black))
  52. // Triangle with the color of the last gradient color
  53. Triangle(isSmallDevice: isSmallDevice)
  54. .fill(triangleColor)
  55. .frame(width: triangleSize, height: triangleSize)
  56. .offset(x: offset)
  57. }
  58. .rotationEffect(.degrees(rotationDegrees))
  59. .shadow(color: Color.black.opacity(0.33), radius: 3)
  60. }
  61. }