TrendShape.swift 2.6 KB

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