我们如何在 SwiftUI 中使用图像创建自定义垂直仪表?

问题描述 投票:0回答:1

我是 SwiftUI 的新手,我正在尝试使用 SwiftUI 设计车辆的速度计,为此我检查了各种解决方案,但所有解决方案都是圆形或线性水平的,但我需要它完全定制。

请找到附件以阐明我要创建的内容。

内容视图

import SwiftUI

struct SpeedometerGaugeStyle: GaugeStyle {
   private var numberOfIterations = 40
   private var purpleGradient = LinearGradient(gradient: Gradient(colors:
                                                                [ Color.red,
                                                                  Color.green,
                                                                  Color.blue
                                                                ]),
                                            startPoint: .topLeading, endPoint: .bottomTrailing)
   func makeBody(configuration: Configuration) -> some View {
      VStack {
          ForEach((1...20), id: \.self) { index in
              RoundedRectangle(cornerSize: CGSize(width: 100, height: 10))
                  .frame(width: (Double(100 - ( index * 2 )) ), height: 10)
                  .foregroundStyle(ColorGradient.putIndex(index: index))
          }
      }
  }



  struct ColorGradient  {
    
    static func putIndex(index : Int) -> LinearGradient {
        
        switch index {
        case 0...4:
            return LinearGradient(colors: [
                Color.red,
                Color.red.opacity(0.7),
                Color.red.opacity(0.6),
                Color.red.opacity(0.5)
            ],
            startPoint: .bottom, endPoint: .top)
        case 4...8:
            return LinearGradient(colors: [
                Color.orange,
                Color.orange.opacity(0.7),
                Color.orange.opacity(0.6),
                Color.orange.opacity(0.5)
            ],
            startPoint: .bottom, endPoint: .top)
            
        case 8...16:
            return LinearGradient(colors: [
                Color.cyan,
                Color.cyan.opacity(0.7),
                Color.cyan.opacity(0.6),
                Color.cyan.opacity(0.5)
            ],
            startPoint: .bottom, endPoint: .top)
        default:
            return LinearGradient(colors: [
                Color.green,
                Color.green.opacity(0.8),
                Color.green.opacity(0.9),
                Color.green.opacity(1.0)
            ],
            startPoint: .bottom, endPoint: .top)
       }
     }
   }
 }


struct CustomGaugeView: View {

  @State private var currentSpeed = 45.0
  @State private var animateGradient = false

  var body: some View {
      VStack {
          Gauge(value: currentSpeed, in: 0...160) {
              Text(currentSpeed.debugDescription)
          } currentValueLabel: {
              Text("\(currentSpeed.formatted(.number))")
                  .foregroundColor(Color.white)
          }
          .gaugeStyle(SpeedometerGaugeStyle())
          .frame(width: 200, height: 300)
        
          Spacer()
        
          Slider(value: $currentSpeed, in: 0...160) {
              EmptyView()
          }
          Spacer()
      }
   }
 }

主要

  @main
  struct Speedometer_DemoApp: App {
   var body: some Scene {
      WindowGroup {
          CustomGaugeView()
            .previewDisplayName("CustomGaugeView")
      }
    }
  }

任何人都可以帮助我使用 SwiftUI 获取这种类型的仪表吗? 预先感谢

swift swiftui gauge
1个回答
0
投票

您需要配置值才能使其工作。

struct SpeedometerGaugeStyle: GaugeStyle {
private var numberOfIterations = 20

private var purpleGradient = LinearGradient(gradient: Gradient(colors:
                                                                [ Color.red,
                                                                  Color.green,
                                                                  Color.blue
                                                                ]),
                                            startPoint: .topLeading, endPoint: .bottomTrailing)


func makeBody(configuration: Configuration) -> some View {
    GeometryReader { geometry in
        VStack(alignment: .leading) {
            ForEach((0... numberOfIterations).reversed(), id: \.self) { index in
                   RoundedRectangle(cornerSize: CGSize(width: 100, height: 10))
                       .frame(width: (Double(100 + ( index * 2 )) ), height: 5)
                       .foregroundStyle(ColorGradient.putIndex(index: index))
                       .opacity((configuration.value * numberOfIterations) > Double(index) ? 1 : 0.3)
               }
           }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
  }
}

对齐方式:vstack 中的 .leading 将其推到一侧 .trailing 将其切换到另一侧。

我还切换了颜色渐变,从绿色变为红色

struct ColorGradient  {

static func putIndex(index : Int) -> LinearGradient {

    switch index {
    case 0...4:
        return LinearGradient(colors: [
            Color.green,
            Color.green.opacity(0.8),
            Color.green.opacity(0.9),
            Color.green.opacity(1.0)
        ],
                              startPoint: .bottom, endPoint: .top)

    case 4...8:
        return LinearGradient(colors: [
            Color.cyan,
            Color.cyan.opacity(0.7),
            Color.cyan.opacity(0.6),
            Color.cyan.opacity(0.5)
        ],
                              startPoint: .bottom, endPoint: .top)

    case 8...15:
        return LinearGradient(colors: [
            Color.orange,
            Color.orange.opacity(0.7),
            Color.orange.opacity(0.6),
            Color.orange.opacity(0.5)
        ],
                              startPoint: .bottom, endPoint: .top)
    default:
        return LinearGradient(colors: [
            Color.red,
            Color.red.opacity(0.7),
            Color.red.opacity(0.6),
            Color.red.opacity(0.5)
        ],
                              startPoint: .bottom, endPoint: .top)
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.