You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI中使用图片创建自定义垂直车辆车速仪表盘

自定义SwiftUI车速表实现方案

你的现有代码已经搭建了基础的刻度布局,但缺少根据车速动态激活对应刻度的核心逻辑,同时需要优化布局和状态切换的流畅性。以下是完善后的实现代码:

完整ContentView代码

import SwiftUI

struct SpeedometerGaugeStyle: GaugeStyle {
    // 总刻度数,对应0-160车速区间,每8单位一个刻度
    private let totalTicks = 20
    private let maxSpeed: Double = 160
    
    func makeBody(configuration: Configuration) -> some View {
        let progress = configuration.value / maxSpeed
        // 计算当前需要高亮的刻度数量
        let activeTicks = Int(progress * Double(totalTicks))
        
        VStack(spacing: 4) {
            ForEach(1...totalTicks, id: \.self) { index in
                // 刻度长度随索引递增逐步缩短(从长到短排列)
                let tickWidth = Double(100 - (index * 2))
                RoundedRectangle(cornerSize: CGSize(width: 10, height: 10))
                    .frame(width: tickWidth, height: 10)
                    // 激活刻度用对应渐变,未激活刻度显示灰色
                    .foregroundStyle(index <= activeTicks ? ColorGradient.getGradient(for: index) : .gray.opacity(0.3))
                    .animation(.easeInOut(duration: 0.2), value: activeTicks)
            }
        }
        .frame(width: 200)
        // 在顶部叠加显示当前车速数值
        .overlay(alignment: .top) {
            configuration.currentValueLabel
                .font(.largeTitle)
                .fontWeight(.bold)
                .padding(.bottom, 20)
        }
    }
    
    struct ColorGradient {
        static func getGradient(for index: Int) -> LinearGradient {
            switch index {
            case 1...4:
                return LinearGradient(colors: [
                    .red,
                    .red.opacity(0.7),
                    .red.opacity(0.5)
                ], startPoint: .bottom, endPoint: .top)
            case 5...8:
                return LinearGradient(colors: [
                    .orange,
                    .orange.opacity(0.7),
                    .orange.opacity(0.5)
                ], startPoint: .bottom, endPoint: .top)
            case 9...16:
                return LinearGradient(colors: [
                    .cyan,
                    .cyan.opacity(0.7),
                    .cyan.opacity(0.5)
                ], startPoint: .bottom, endPoint: .top)
            default:
                return LinearGradient(colors: [
                    .green,
                    .green.opacity(0.8),
                    .green.opacity(0.6)
                ], startPoint: .bottom, endPoint: .top)
            }
        }
    }
}

struct CustomGaugeView: View {
    @State private var currentSpeed = 45.0
    @State private var animateGradient = false
    
    var body: some View {
        VStack(spacing: 30) {
            Gauge(value: currentSpeed, in: 0...160) {
                Text("车速表")
                    .foregroundColor(.white)
                    .font(.title)
            } currentValueLabel: {
                Text("\(Int(currentSpeed))")
                    .foregroundColor(.white)
            }
            .gaugeStyle(SpeedometerGaugeStyle())
            .frame(height: 300)
            .background(.black.opacity(0.8))
            .cornerRadius(20)
            
            Slider(value: $currentSpeed, in: 0...160, step: 1) {
                Text("调整车速")
            } minimumValueLabel: {
                Text("0")
            } maximumValueLabel: {
                Text("160")
            }
            .tint(.blue)
        }
        .padding()
        .background(.gray.opacity(0.1))
        .preferredColorScheme(.dark)
    }
}

Main入口代码

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

关键优化说明

  • 动态刻度激活:通过configuration.value计算车速进度,自动确定需要高亮的刻度数量,未激活刻度统一显示灰色
  • 平滑动画过渡:给刻度颜色切换添加动画,让车速变化时视觉过渡更自然
  • 视觉布局优化:将车速数值固定在仪表盘顶部,添加深色背景增强科技感,完善Slider的刻度显示
  • 颜色区间修正:修复了原代码中区间重复匹配的问题,确保每个刻度对应唯一的颜色渐变

内容的提问来源于stack exchange,提问作者Keval Gajjar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 17:19:53