鸿蒙 ArkUI 数据可视化图例对照表:组件化设计与实现

📅 2026/7/6 1:36:48
鸿蒙 ArkUI 数据可视化图例对照表:组件化设计与实现
鸿蒙 ArkUI 数据可视化图例对照表组件化设计与实现一、引言图例Legend是数据可视化中连接数据与视觉编码的桥梁。用户通过颜色与标签的对照关系快速理解图表含义。随着 HarmonyOS NEXT 普及ArkTS 声明式 UI 成为主流但新版 ArkUI 移除了 Table 等旧组件使许多开发者对表格布局感到困惑。本文以完整图例对照表为案例讲解如何用 Row Column 弹性布局、颜色矩形、文字标签和线性渐变 API 构建可复用的图例组件库。二、需求分析与总体设计2.1 功能需求颜色标识每个条目包含带圆角的颜色矩形。标签文字说明颜色对应的分类名称。附加描述辅助文字温度范围、占比等。连续型图例渐变色彩条配合刻度标签。离散型图例表格形式的多行分类。多组并存分割线区隔可滚动浏览。2.2 技术选型需求方案理由UI 框架ArkTS ArkUI鸿蒙原生声明式框架表格布局Row Column layoutWeightAPI 11 已移除 Table颜色矩形Row backgroundColor borderRadius轻量高效渐变条Row linearGradient()原生 API列表渲染ForEach 数组内置能力2.3 架构概览IndexEntry 根组件 └─ Scroll → Column ├─ 页面标题 ├─ GradientBar连续型渐变图例 ├─ LegendTableGroup × 3 │ ├─ SectionTitle 副标题 │ └─ 表格 Column → LegendTableRow 列表 │ ├─ ColorSwatch色块 │ └─ LegendCell × 2 └─ 底部版权三、核心组件实现3.1 数据模型interfaceLegendItem{color:ResourceColor;label:string;description:string;}预置三种数据源温度 / 占比 / 评分constTEMPERATURE_LEGENDS:LegendItem[][{color:#FF4444,label:高温,description:≥ 35°C},{color:#FF8C00,label:炎热,description:30°C – 34°C},{color:#FFD700,label:温暖,description:20°C – 29°C},{color:#87CEEB,label:凉爽,description:10°C – 19°C},{color:#1E90FF,label:寒冷,description:0°C – 9°C},{color:#0000CD,label:严寒,description: 0°C},];constPROPORTION_LEGENDS:LegendItem[][{color:#5470C6,label:A 类,description:销售额占比 45%},{color:#91CC75,label:B 类,description:销售额占比 28%},{color:#FAC858,label:C 类,description:销售额占比 15%},{color:#EE6666,label:D 类,description:销售额占比 12%},];constLEVEL_LEGENDS:LegendItem[][{color:#00BFFF,label:优秀,description:评分 ≥ 90},{color:#32CD32,label:良好,description:75 ≤ 评分 90},{color:#FFD700,label:中等,description:60 ≤ 评分 75},{color:#FF6347,label:较差,description:评分 60},];3.2 ColorSwatch颜色矩形使用空 Row backgroundColor比 Shape Rect 更轻量Componentstruct ColorSwatch{swatchColor:ResourceColor#5470C6;swatchSize:number20;build(){Row().width(this.swatchSize).height(this.swatchSize).backgroundColor(this.swatchColor).borderRadius(4)}}Shape Rect 渲染有额外开销空 Row 本质就是矩形区域加 backgroundColor 即可。4px 圆角让色块不显生硬。3.3 LegendCell表格单元格封装 Text 通用样式Componentstruct LegendCell{content:string;fontWeight:FontWeightFontWeight.Normal;fontColor:ResourceColor#333333;build(){Text(this.content).fontSize(14).fontWeight(this.fontWeight).fontColor(this.fontColor).textAlign(TextAlign.Start).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})}}注意API 11 中文字溢出省略语法已从.overflow(TextOverflow.Ellipsis)变为.textOverflow({ overflow: TextOverflow.Ellipsis })这是迁移时最常见的坑。3.4 LegendTableRow表格行三列布局支持表头/数据行双模式Componentstruct LegendTableRow{color:ResourceColor#5470C6;label:string;desc:string;isHeader:booleanfalse;build(){Row(){Row(){if(this.isHeader){Text(#).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#666666)}else{ColorSwatch({swatchColor:this.color,swatchSize:20})}}.width(60).justifyContent(FlexAlign.Center)LegendCell({content:this.label,fontWeight:this.isHeader?FontWeight.Bold:FontWeight.Medium,fontColor:this.isHeader?#666666:#333333}).layoutWeight(1)LegendCell({content:this.desc,fontWeight:this.isHeader?FontWeight.Bold:FontWeight.Normal,fontColor:this.isHeader?#666666:#888888}).layoutWeight(1.2)}.width(100%).height(this.isHeader?40:48).padding({left:8,right:8}).backgroundColor(this.isHeader?#f8f9fa:Color.White).borderWidth({bottom:1}).borderColor({bottom:#f0f0f0})}}三列弹性布局首列固定 60px 居中次列layoutWeight(1)第三列layoutWeight(1.2)略宽。isHeader控制表头/数据行的颜色、字号、背景差异。逐行底部分隔线避免整表双倍边框。3.5 SectionTitle区块标题左侧色条 粗体标题色条颜色与图例主题一致Componentstruct SectionTitle{title:string;iconColor:ResourceColor#5470C6;build(){Row(){Column().width(4).height(18).backgroundColor(this.iconColor).borderRadius({topLeft:2,bottomLeft:2})Text(this.title).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#222222).margin({left:10})}.width(100%).alignItems(VerticalAlign.Center).margin({top:16,bottom:4})}}3.6 GradientBar连续型渐变条使用原生linearGradient()API深蓝 → 红色六段渐变Componentstruct GradientBar{build(){Column(){Row().width(100%).height(28).borderRadius(6).linearGradient({direction:GradientDirection.Right,colors:[[#0000CD,0.0],[#1E90FF,0.2],[#87CEEB,0.35],[#FFD700,0.5],[#FF8C00,0.7],[#FF4444,1.0],]})Row(){Text(低).fontSize(13).fontColor(#999999)Blank()Text(中).fontSize(13).fontColor(#999999)Blank()Text(高).fontSize(13).fontColor(#999999)}.width(100%).margin({top:4})}.width(100%)}}色标偏移量非均匀分布蓝色区宽、红色区紧模拟低温区间大的感知。刻度通过Blank()自然三等分。注意linearGradient不可用于Shape.fill()——后者仅接受纯色ResourceColor。3.7 LegendTableGroup表格组组装标题、副标题和表格行为完整区块Componentstruct LegendTableGroup{title:string;subtitle:string;iconColor:ResourceColor#5470C6;legends:LegendItem[][];build(){Column(){SectionTitle({title:this.title,iconColor:this.iconColor})Text(this.subtitle).fontSize(13).fontColor(#999999).width(100%).margin({bottom:8})Column(){LegendTableRow({color:#555555,label:标签,desc:说明,isHeader:true})ForEach(this.legends,(item:LegendItem){LegendTableRow({color:item.color,label:item.label,desc:item.description})})}.width(100%).border({width:{top:1,bottom:1},color:#e0e0e0}).borderRadius(8).clip(true)}.width(100%)}}外层border({ top:1, bottom:1 })加上下边框borderRadius(8)clip(true)形成圆角卡片。3.8 模拟 Table 的原理Row Column 替代原生 Table首列固定宽后续layoutWeight按比例分配每行底部borderWidth({ bottom: 1 })分隔isHeader切换表头/数据行样式。对固定结构的图例展示完全够用。四、页面组装4.1 主页面 IndexEntryComponentstruct Index{build(){Scroll(){Column(){Text(数据可视化图例对照表).fontSize(26).fontWeight(FontWeight.Bold).fontColor(#1a1a2e).width(100%).margin({top:28,bottom:4})Text(Data Visualization Legend).fontSize(13).fontColor(#aaaaaa).width(100%).margin({bottom:20})SectionTitle({title:连续型渐变图例 (Sequential),iconColor:#FF8C00})Text(适用于热力图 / 气象图表).fontSize(13).fontColor(#999999).width(100%).margin({bottom:8})GradientBar()Divider().height(1).color(#eeeeee).margin({top:20,bottom:4})LegendTableGroup({title:温度等级 (Temperature),iconColor:#FF4444,subtitle:适用于热力图 / 气象图表,legends:TEMPERATURE_LEGENDS})LegendTableGroup({title:占比分类 (Proportion),iconColor:#91CC75,subtitle:适用于饼图 / 环形图 / 堆叠图,legends:PROPORTION_LEGENDS})LegendTableGroup({title:评分等级 (Rating Level),iconColor:#00BFFF,subtitle:适用于仪表盘 / 评分图 / 状态标识,legends:LEVEL_LEGENDS})Divider().height(1).color(#eeeeee).margin({top:24,bottom:12})Row(){Text(Powered by ).fontSize(12).fontColor(#bbbbbb)Text(HarmonyOS ArkUI).fontSize(12).fontColor(#5470C6).fontWeight(FontWeight.Medium)}.width(100%).justifyContent(FlexAlign.Center).margin({bottom:32})}.width(100%).padding({left:16,right:16})}.backgroundColor(#ffffff).height(100%)}}主标题 #1a1a2e区块标题 #222222标签 #333333描述 #888888。五、常见问题与优化私有属性限制ArkTS 的private禁止构造传参移除即可。TextOverflow 变更API 11 改用.textOverflow({ overflow: TextOverflow.Ellipsis })。LinearGradient不可用于 Shape.fill()需用容器组件.linearGradient()方法。Table 缺失用 Row Column layoutWeight 替代。性能ForEach 用 key 加速差异化更新大数据量用 LazyForEach 虚拟列表。六、扩展建议主题系统颜色值抽取为资源引用支持深色模式。交互点击筛选、折叠展开、长按提示。图例类型形状/线型/大小/复合图例。国际化用$r(app.string.xxx)实现多语言。动画用animateTo和animation添加入场效果。七、总结本文讲解了在鸿蒙 ArkUI 中用 Row Column 弹性布局、颜色矩形、文字标签和线性渐变 API 构建图例组件库的方法。六个独立组件实现了高内聚低耦合。关键语法组件属性默认访问级别才能构造传参textOverflow({ overflow: TextOverflow.Ellipsis })是 API 11 正确用法linearGradient 不可用于 Shape.fill用 Row Column 替代已移除的 Table 组件。本案例已在 HarmonyOS NEXTAPI 6.1.1/24编译通过源码位于entry/src/main/ets/pages/Index.ets。