一、引言

在物联网、智能硬件、工业控制、数据看板等场景中,仪表盘是展示实时数据最直观的方式。温度监测、设备转速、油量指示、性能评分——这些场景都需要一个圆弧形的"仪表"来呈现当前值与范围的相对关系。与横条式的进度条(Progress)不同,仪表盘(Gauge)通过圆弧张角、渐变色填充和中心数值的组合,给人更强的"实时监控"视觉感受。

在传统开发中,实现圆弧仪表盘需要 Canvas 绘图:计算圆弧路径、起点角度、终点角度、极坐标转换到笛卡尔坐标、渐变色映射、描边宽度控制……每一步都是数学和绘图 API 的综合运用。而 HarmonyOS 提供了 Gauge 组件——一个内置完整仪表盘渲染逻辑的圆弧仪表组件,通过声明式 API 即可实现从基本仪表到定制渐变色、张角控制、阴影效果的所有功能。

本文通过一个设备温度监控 Demo 深入讲解 Gauge 组件的核心用法:如何设置圆弧的张角范围(startAngle/endAngle)?如何配置渐变色数组?如何控制描边宽度?以及如何与 Slider 联动实现手动 + 自动双模式监控。

阅读完本文,你将能够:

  • 使用 Gauge 组件替代自建 Canvas 仪表方案
  • 掌握 startAngle/endAngle 张角控制
  • 掌握 colors 渐变色数组的色彩配置
  • 理解 Gauge 与 Progress(Ring)的区别和各自适用场景
  • 构建完整的温度监控仪表盘

二、Gauge 组件 API 总览

2.1 构造函数

Gauge(options: GaugeOptions)
interface GaugeOptions {
  value: number;   // 当前值
  min?: number;    // 最小值,默认 0
  max?: number;    // 最大值,默认 100
}
参数 类型 默认值 说明
value number 必填 当前仪表值,范围 [min, max]
min number 0 仪表量程下限
max number 100 仪表量程上限

2.2 链式方法

// 动态值更新
.value(value: number): GaugeAttribute

// 起始角度(12点钟方向为 0 度,顺时针计算)
.startAngle(angle: number): GaugeAttribute

// 结束角度
.endAngle(angle: number): GaugeAttribute

// 渐变色数组(多色分段)
.colors(colors: Array<ColorStop>): GaugeAttribute
// ColorStop = [ResourceColor, number],如 [ResourceColor, 0] [ResourceColor, 1]

// 描边宽度
.strokeWidth(value: Length): GaugeAttribute

// 轨迹阴影
.trackShadow(value: ShadowOptions): GaugeAttribute

// 尺寸(通用属性)
.width(value: Length)
.height(value: Length)
方法 说明
.value(number) 动态设置当前值,配合 @State 变量实现实时更新
.startAngle(number) 圆弧起始角度(°,顺时针)
.endAngle(number) 圆弧结束角度(°,顺时针)
.colors(Array<ColorStop>) 渐变色数组,[颜色, 位置比例] 格式
.strokeWidth(Length) 圆弧描边宽度(粗细)

2.3 角度坐标系统

Gauge 的角度系统以12 点钟方向为 0°,顺时针递增:

角度 方向
12 点(正上方)
90° 3 点(正右方)
180° 6 点(正下方)
270° 9 点(正左方)
360° 回到 12 点

典型的仪表盘配置:

  • 底部半圆弧startAngle(225), endAngle(315)——或更常用的 .startAngle(210).endAngle(150),形成底部约 300°的圆弧
  • 顶部半圆弧startAngle(135).endAngle(45)——形成顶部约 270°的圆弧

2.4 Gauge vs Progress(Ring) 对比

特性 Gauge Progress(Ring)
圆弧张角 自定义 startAngle/endAngle 固定 360° 完整圆环
颜色 渐变色数组(多色、多段) 单一 color
描边 strokeWidth style.strokeWidth
中心文字 通过独立 Text 组件 无内置
刻度线 ScaleRing 有刻度
视觉层次 仪表感强,适合突出展示 进度感强,适合占比展示
典型场景 温度表、转速表、油量计 完成率、内存占用、下载进度

核心区别:Gauge 是不完整的圆弧(扇面),Progress Ring 是完整的圆环(360°)。 Gauge 通过角度控制呈现"仪表"的视觉效果,Progress Ring 呈现"环状条"的进度感。
在这里插入图片描述

三、Demo 设计:设备温度监控

3.1 功能概述

Demo 是一个设备温度监控页面,模拟 IoT 硬件或服务器机房的温度监控面板:

  1. CPU 温度仪表:主仪表盘(210°→150°,约 300° 张角),大号圆弧 + 数值 + 状态标签
  2. GPU 温度仪表:次仪表盘(225°→135°,约 270° 张角),略小的圆弧展示
  3. 渐变色阈值:温度 < 65°C 绿色渐变,65-85°C 橙色渐变,≥ 85°C 红色渐变
  4. 模拟温度:setInterval 随机生成 CPU/GPU 温度(2 秒间隔)
  5. 手动调节:两个 Slider 手动拖动 CPU 和 GPU 温度
  6. 阈值图例:底部展示三个温度区间的颜色和文字说明

3.2 交互点

# 交互 说明
1 模拟温度按钮 setInterval 随机模拟 CPU/GPU 温度,仪表实时响应
2 Slider 手动调节 拖动两个 Slider 分别控制 CPU 和 GPU 温度
3 渐变色阈值 跨越 65°C/85°C 阈值时圆弧颜色实时切换
4 状态标签 颜色标签动态变化(正常/偏高/高温/过热)
在这里插入图片描述

四、完整代码实现

4.1 状态变量

@State cpuTemp: number = 45;
@State gpuTemp: number = 38;
@State isSimulating: boolean = false;
private timerId: number = -1;

4.2 颜色阈值逻辑

getTempColor(temp: number): string {
  if (temp >= 85) return '#FF4D4F';
  if (temp >= 65) return '#FF9800';
  return '#52C41A';
}

getTempLabel(temp: number): string {
  if (temp >= 90) return '过热';
  if (temp >= 85) return '高温';
  if (temp >= 65) return '偏高';
  if (temp >= 40) return '正常';
  return '偏低';
}

getGaugeColors(temp: number): Array<[ResourceColor, number]> {
  if (temp >= 85) return [['#FF4D4F', 0], ['#FF7875', 0.6], ['#FF4D4F', 1]];
  if (temp >= 65) return [['#FF9800', 0], ['#FFB84D', 0.6], ['#FF9800', 1]];
  return [['#52C41A', 0], ['#73D13D', 0.6], ['#52C41A', 1]];
}

三个辅助方法构建了完整的颜色语义系统:

  • getTempColor:返回单一颜色,用于数值文字和状态标签背景
  • getTempLabel:返回中文标签,90°C 以上单独标注"过热"
  • getGaugeColors:返回渐变色数组——三段式渐变,每段包含起始色(位置 0)、中间高亮色(位置 0.6)、结束色(位置 1),形成中间亮、两端暗的视觉效果

4.3 CPU 温度仪表

Gauge({ value: this.cpuTemp, min: 0, max: 100 })
  .value(this.cpuTemp)
  .startAngle(210)
  .endAngle(150)
  .colors(this.getGaugeColors(this.cpuTemp))
  .strokeWidth(18)
  .width(200)
  .height(130)

逐行解析:

  • min: 0, max: 100:温度量程 0-100°C。value 在 [0, 100] 区间内映射为圆弧的填充比例
  • .startAngle(210).endAngle(150):关键配置。从 210°(约 7 点钟方向,左下)逆时针画到 150°(约 5 点钟方向,右下),形成底部约 300° 的大圆弧。如果 startAngle(150).endAngle(210) 则相反(顶部小弧)
  • .colors(array):渐变色数组,根据当前温度动态切换绿/橙/红三套渐变色。每个元素为 [颜色字符串, 位置比例],位置比例 0 = 起点,1 = 终点
  • .strokeWidth(18):圆弧描边宽度 18vp,较粗的弧线使仪表视觉上更厚重
  • .width(200).height(130):宽 200、高 130。注意 Gauge 的高度约为宽度的一半,因为底部圆弧的高度占用空间较少

4.4 配套温度数值

由于 Gauge 不像 TextTimer 那样内置文字显示区域,温度数值通过独立的 Text 组件展示:

Text(`${this.cpuTemp}°C`)
  .fontSize(48)
  .fontColor(this.getTempColor(this.cpuTemp))
  .fontWeight(FontWeight.Bold)
  .fontFamily('monospace')
  .margin({ top: 8 })

Text(this.getTempLabel(this.cpuTemp))
  .fontSize(16)
  .fontColor('#FFFFFF')
  .fontWeight(FontWeight.Bold)
  .padding({ top: 4, bottom: 4, left: 20, right: 20 })
  .borderRadius(12)
  .backgroundColor(this.getTempColor(this.cpuTemp))
  .margin({ top: 8 })

数值使用 48sp 大号等宽字体,颜色与仪表圆弧颜色一致。下方状态标签(“正常”/“偏高”/“高温”)使用白字 + 对应颜色背景的圆角标签,与数值形成层次分组。

4.5 GPU 温度仪表

Gauge({ value: this.gpuTemp, min: 0, max: 100 })
  .value(this.gpuTemp)
  .startAngle(225)
  .endAngle(135)
  .colors(this.getGaugeColors(this.gpuTemp))
  .strokeWidth(14)
  .width(160)
  .height(110)

GPU 仪表与 CPU 仪表的差异:

  • 张角窄:startAngle(225).endAngle(135) 形成约 270° 的圆弧,比 CPU 的 300° 略窄
  • 尺寸小:160×110 vs 200×130,主次分明
  • 描边细:14vp vs 18vp,视觉上更轻量

两个仪表共用同一套颜色逻辑(getGaugeColors/getTempLabel),但各自显示独立的温度值。

4.6 模拟温度更新

startSimulate() {
  this.isSimulating = true;
  this.timerId = setInterval(() => {
    this.cpuTemp = 30 + Math.floor(Math.random() * 65);
    this.gpuTemp = 25 + Math.floor(Math.random() * 60);
  }, 2000);
}
  • CPU 温度范围 30-95°C(30 + [0,65)),GPU 温度范围 25-85°C(25 + [0,60)
  • 2 秒间隔,平衡实时感和渲染负担

4.7 Slider 手动调节

Slider({
  value: this.cpuTemp,
  min: 0,
  max: 100,
  step: 1,
  style: SliderStyle.OutSet
})
  .blockColor(this.getTempColor(this.cpuTemp))
  .trackColor('#F2F3F5')
  .selectedColor(this.getTempColor(this.cpuTemp))
  .layoutWeight(1)
  .onChange((value: number) => { this.cpuTemp = value; })

Slider 的 blockColorselectedColor 也通过 getTempColor 绑定颜色阈值,拖动手柄时滑块颜色与 Gauge 颜色保持同步。

4.8 startAngle/endAngle 的配置逻辑

这两个角度参数决定了圆弧的形状。理解它们的计算方式:

CPU 仪表: startAngle(210), endAngle(150)
  起点 210° = 7 点方向(左下)
  终点 150° = 5 点方向(右下)
  填充方向 = 从起点顺时针到终点
  圆弧张角 = 300°(210° → 150°,经过 270°→300°→...→150°)

GPU 仪表: startAngle(225), endAngle(135)
  起点 225° = 7:30 方向(更左下)
  终点 135° = 4:30 方向(更右下)
  圆弧张角 = 270°

CPU 仪表张角更宽(300°),视觉上更"饱满",适合重点展示。GPU 仪表张角较窄(270°),视觉上更"轻盈",适合次要指标。

五、关键技术点详解

5.1 colors 渐变色数组的结构

.colors() 参数是 Array<[ResourceColor, number]> 类型,每个元素为 [颜色, 位置比例]

// 三段绿色渐变
[['#52C41A', 0],    // 起点:深绿
 ['#73D13D', 0.6],  // 60%:亮绿(高光)
 ['#52C41A', 1]]    // 终点:深绿

视觉效果:从深绿过渡到亮绿再回到深绿,圆弧的中段(60% 位置)最亮。这种"两端暗、中间亮"的渐变模拟了金属表面的反光效果,比单一颜色更立体。

也可以使用更多分段实现更复杂的颜色过渡:

// 四段警示渐变
[['#52C41A', 0], ['#FFEB3B', 0.4], ['#FF9800', 0.7], ['#FF4D4F', 1]]

5.2 strokeWidth 与圆弧视觉重量

strokeWidth 越大,圆弧越粗,视觉上越"厚重";越小越细,越"精致":

strokeWidth 视觉效果 适用场景
6-10 纤细、轻量 嵌入式小仪表、多指标卡片
12-18 标准、清晰 主仪表盘、单指标突出展示
20-28 粗壮、厚重 大屏监控、车机仪表

在本 Demo 中,CPU 仪表使用 18vp(主指标突出),GPU 仪表使用 14vp(辅助指标轻量化)。

5.3 宽度 vs 高度的比例关系

Gauge 组件的尺寸设置有一个隐含规则:高度约为宽度的一半。这是由圆弧的几何形状决定的——从 210° 到 150° 的圆弧在垂直方向上的投影约等于圆弧半径的一半。

width=200, height=130 → 底部圆弧占据约 130vp 的垂直空间
width=160, height=110 → 底部圆弧占据约 110vp 的垂直空间

如果 height 设置得太小,圆弧可能被裁剪;设置得太大,圆弧上方出现大量空白。推荐比例:height ≈ width × 0.65

5.4 Gauge vs Progress(Ring) 的适用指南

选 Gauge 当… 选 Progress(Ring) 当…
需要不完整圆弧(< 360°) 需要完整圆环
需要渐变色分段 单色即可满足
"仪表"语义(温度、油量、压力) "进度"语义(完成百分比)
作为页面核心展示元素 作为行内或卡片中的状态指示
视觉上需要突出、大尺寸 多指标同时展示、节省空间

一个页面上可以同时使用 Gauge 和 Progress Ring:Gauge 作为核心指标的大号仪表,Progress Ring 作为辅助指标的小号圆环。

5.5 与 Text 组件的组合模式

Gauge 本身不提供中心文字显示——这一点与某些 UI 框架的 Gauge 不同(如 ECharts 的仪表盘图表自带中心文字)。在 ArkUI 中,中心数值通过独立的 Text 组件实现:

// 典型模式:Gauge + Text 垂直排列
Column() {
  Gauge({ value: this.cpuTemp, min: 0, max: 100 })
    .startAngle(210).endAngle(150)
  Text(`${this.cpuTemp}°C`)
    .fontSize(48)
}
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)

Text 组件放在 Gauge 之后(视觉上位于圆弧下方),使用 .justifyContent(FlexAlign.Center) 确保整体居中对齐。

六、运行效果

6.1 初始状态

CPU 仪表显示 45°C,绿色渐变圆弧,大号 “45°C” 绿色数字,绿色"正常"状态标签。GPU 仪表显示 38°C,略小,张角略窄。

6.2 模拟温度

点击"模拟温度"按钮,CPU 和 GPU 温度每 2 秒随机更新一次。当 CPU 温度达到 65°C 以上时,圆弧从绿色渐变切换为橙色渐变,标签变为"偏高"橙色。达到 85°C 以上时切换为红色渐变,"高温"红色标签。

6.3 手动调节

拖动 CPU Slider 到 92°C——圆弧变为红色渐变,数值和标签同步变红,标签变为"过热"。Sliders 的滑块和选中轨道颜色同步变红。

七、最佳实践与注意事项

7.1 角度配置建议

场景 startAngle endAngle 效果
底部圆弧(推荐) 210 150 约 300° 宽弧,类似汽车仪表
窄底弧 225 135 约 270° 窄弧,适合小尺寸
顶部圆弧 135 45 约 270° 顶弧,适合罕见布局
全圆弧 180 180 360° 全圆弧(几乎闭合)

7.2 颜色配置建议

颜色应始终与数据语义保持一致:

// 推荐的三色方案
正常 ← 绿色系 → 让用户放心
警告 ← 橙色系 → 引起用户注意
危险 ← 红色系 → 警示用户立即关注

不建议使用黄色作为背景色(对比度不足),但可以用于渐变色数组中的中间过渡色。

7.3 常见问题

Q: Gauge 可以显示刻度线吗?

A: Gauge 本身不支持刻度线。如需刻度,可以使用 Progress ScaleRing(有刻度但无张角控制),或用 Canvas 组件在 Gauge 外围自绘刻度。

Q: 如何让 Gauge 显示百分比符号?

A: 在独立的 Text 组件中添加:“%” 等符号:Text(${this.value}%)

Q: startAngle 可以大于 endAngle 吗?

A: 可以。填充方向始终从 startAngle 顺时针到 endAngle。如 startAngle(210).endAngle(150),从 210° 顺时针经过 270°→360°(0°)→90°→150°,形成 300° 的大弧。

Q: Gauge 支持动画吗?

A: 支持。当 @State 变量变化时,Gauge 自动触发约 300ms 的平滑过渡动画。

7.4 性能建议

  • Gauge 基于 Canvas 渲染,单个仪表性能开销很小
  • 页面同时显示 4-6 个 Gauge 不会出现性能问题
  • 避免在 setInterval 中设置过短的间隔(< 500ms),高频更新会加重渲染负担

八、拓展思考

8.1 从温度监控到 IoT 设备面板

Gauge 是 IoT 和智能硬件场景的核心展示组件。扩展后的 IoT 面板可以包含:

  • 多设备仪表:每个传感器一个 Gauge(温度/湿度/气压/PM2.5)
  • 历史趋势:Gauge 下方加折线图展示历史变化
  • 报警联动:当 Gauge 进入红色阈值时触发通知

8.2 与其他组件的配合

  • Gauge + Slider:手动调节参数值(本 Demo 实现)
  • Gauge + TextClock:仪表 + 实时数字时钟,适合监控大屏
  • Gauge + Progress:Gauge 展示主指标(CPU 温度),Progress 展示辅助指标(风扇转速)
  • Gauge + Toggle:切换多个设备的温度显示
  • Gauge + CustomDialog:点击仪表弹出详情弹窗

九、总结

本文通过一个设备温度监控的实战 Demo,深入讲解了 HarmonyOS Gauge 仪表盘组件的核心用法:

  1. Gauge 构造函数value/min/max 定义仪表量程和当前值
  2. startAngle/endAngle:圆弧张角控制,典型配置 210°→150° 形成底部圆弧
  3. colors 渐变色数组[颜色, 位置比例] 格式的多段渐变色,支持阈值动态切换
  4. strokeWidth:控制圆弧视觉重量,主仪表粗、次仪表细
  5. 数值展示模式:独立 Text 组件与 Gauge 组合,形成"圆弧 + 数值 + 标签"的三层结构
  6. 手动 + 自动双模式:Slider 手动调节 + setInterval 模拟数据

Gauge 是 ArkUI 圆弧仪表展示的标准解决方案。从温度监控到设备转速,从 IoT 面板到工业控制,Gauge 以其丰富的配置选项和声明式 API,帮助开发者用简洁的代码实现专业的仪表盘效果。希望本文能帮助你在实际项目中高效运用 Gauge 组件。


相关文章


本文基于 HarmonyOS NEXT API 24 编写,代码经 DevEco Studio 6.1.1 编译验证通过。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐