尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

HarmonyOS应用开发实战:萌宠日记 - 用Stack绘制自定义图表

HarmonyOS应用开发实战:萌宠日记 - 用Stack绘制自定义图表
📅 发布时间:2026/7/22 17:56:36

HarmonyOS应用开发实战:萌宠日记 - 用Stack绘制自定义图表

前言

数据可视化是健康记录页的核心功能,通过图表直观展示宠物体重变化趋势。在萌宠日记中,我们没有使用第三方图表库,而是使用Stack 组件配合Circle 圆形和Row 网格线,手动绘制了一个轻量级的折线图,展示了 5 个数据点的体重变化。

本文将从萌宠日记的体重折线图实现出发,深入解析 Stack 层叠布局的原理、坐标系构建、数据点绘制,以及如何用基础组件实现自定义图表。

一、体重折线图整体设计

1.1 图表结构

┌─────────────────────────────────────┐ │ 体重变化 单位:kg│ │ ┌─────────────────────────────────┐│ │ │ 6.0 ───────────────────────── ││ ← Y 轴标签 │ │ 5.5 ───────────────────────── ││ ← 网格线 │ │ 5.0 ───────────────────────── ││ │ │ 4.5 ───●───────●───────●──── ││ ← 数据点(Circle) │ │ 4.0 ───────────────────────── ││ │ └─────────────────────────────────┘│ │ 2.0 2.0 2.0 2.0 2.0 │ ← X 轴标签 └─────────────────────────────────────┘

1.2 完整代码

// HealthRecordPage.ets — 体重折线图 Column({ space: 12 }) { // 标题行 Row() { Text('体重变化') .fontSize(16) .fontWeight(FontWeight.Bold) .fontColor('#333333') Blank() Text('单位:kg') .fontSize(12) .fontColor('#999999') } .width('100%') // 图表区域 Column() { Row() { // Y 轴标签 Column() { ForEach(['6.0', '5.5', '5.0', '4.5', '4.0'], (label: string) => { Text(label) .fontSize(10) .fontColor('#999999') .height(36) .textAlign(TextAlign.End) .width(30) }) } // 图表区域 Column() { Stack() { // 网格线 ForEach([0, 1, 2, 3, 4], (i: number) => { Row() .width('100%') .height(1) .backgroundColor('#F0EBE3') .position({ x: 0, y: i * 36 }) }) // 数据点 Row() { ForEach([0, 1, 2, 3, 4], (i: number) => { Circle() .width(8) .height(8) .fill('#42A5F5') .position({ x: i * 50, y: 144 - (i * 18 + 36) }) }) } .width('100%') .height(180) } .width('100%') .height(180) } .layoutWeight(1) } .width('100%') // X 轴标签 Row() { Text('').width(30) // 与 Y 轴标签对齐 ForEach(['2.0', '2.0', '2.0', '2.0', '2.0'], (label: string) => { Text(label) .fontSize(10) .fontColor('#999999') .layoutWeight(1) .textAlign(TextAlign.Center) }) } .width('100%') } .padding(12) .backgroundColor('#FFFFFF') .borderRadius(12) } .width('100%') .padding({ left: 16, right: 16 })

提示:体重折线图完全使用Stack 层叠布局实现。Stack 将网格线(背景层)和数据点(前景层)叠加在一起,通过position属性精确控制每个元素的位置。这是一种轻量级的自定义图表方案,无需引入第三方图表库。

二、Stack 层叠布局

2.1 Stack 组件

Stack() { // 背景层:网格线 // 前景层:数据点 } .width('100%') .height(180)

2.2 层叠关系

Stack 层叠(从下到上) ↓ 第一层:网格线(5 条水平线) ↓ 第二层:数据点(5 个蓝色圆点) ↓ 网格线作为背景,数据点作为前景,叠加显示

三、网格线绘制

3.1 水平网格线

// 5 条水平网格线,每条间隔 36vp ForEach([0, 1, 2, 3, 4], (i: number) => { Row() .width('100%') // 撑满宽度 .height(1) // 线高 1vp .backgroundColor('#F0EBE3') // 米色网格线 .position({ x: 0, y: i * 36 }) // 垂直位置:0, 36, 72, 108, 144 })

3.2 网格线间距

网格线索引Y 位置对应 Y 轴标签
0 (i=0)0vp6.0
1 (i=1)36vp5.5
2 (i=2)72vp5.0
3 (i=3)108vp4.5
4 (i=4)144vp4.0

四、数据点绘制

4.1 Circle 组件

// 数据点 — 蓝色圆形 Circle() .width(8) // 圆点直径 8vp .height(8) // 圆点直径 8vp .fill('#42A5F5') // 蓝色填充 .position({ x: i * 50, y: 144 - (i * 18 + 36) }) // 位置计算

4.2 数据点位置计算

// 数据点位置计算 // X 位置:i * 50(5 个点均匀分布) // Y 位置:144 - (i * 18 + 36) // 图表区域高度 = 180vp // 数据映射范围:4.0-6.0(2.0 范围) // 每单位高度 = 180 / 2.0 = 90vp // 数据点分布 // 点 0: 4.0kg → y = 144 // 点 1: 4.3kg → y = 126 // 点 2: 4.5kg → y = 108 // 点 3: 4.7kg → y = 90 // 点 4: 5.0kg → y = 72

五、坐标轴标签

5.1 Y 轴标签

// Y 轴标签(左侧) Column() { ForEach(['6.0', '5.5', '5.0', '4.5', '4.0'], (label: string) => { Text(label) .fontSize(10) .fontColor('#999999') .height(36) // 与网格线间距一致 .textAlign(TextAlign.End) // 右对齐 .width(30) // 固定宽度 }) }

5.2 X 轴标签

// X 轴标签(底部) Row() { Text('').width(30) // 与 Y 轴标签对齐 ForEach(['2.0', '2.0', '2.0', '2.0', '2.0'], (label: string) => { Text(label) .fontSize(10) .fontColor('#999999') .layoutWeight(1) // 与数据点对齐 .textAlign(TextAlign.Center) }) }

六、图表标题行

6.1 标题设计

Row() { Text('体重变化') .fontSize(16) .fontWeight(FontWeight.Bold) Blank() Text('单位:kg') .fontSize(12) .fontColor('#999999') } .width('100%')

七、图表容器样式

7.1 容器

Column() { // 图表内容 } .padding(12) .backgroundColor('#FFFFFF') .borderRadius(12)

八、动态数据驱动

8.1 数据绑定

// 使用真实数据驱动图表 @State weightData: number[] = [4.0, 4.3, 4.5, 4.7, 5.0] build() { // 根据 weightData 动态绘制数据点 ForEach(this.weightData, (weight: number, index: number) => { Circle() .width(8).height(8) .fill('#42A5F5') .position({ x: index * 50, y: 180 - ((weight - 4.0) / 2.0 * 180) - 18 }) }) }

九、图表扩展

9.1 折线连接

// 在数据点之间添加连接线 // 使用 Path 组件绘制折线 Path() .commands('M 0 144 L 50 126 L 100 108 L 150 90 L 200 72') .stroke('#42A5F5') .strokeWidth(2) .fill('none')

十、最佳实践

10.1 自定义图表设计原则

有序列表 — 自定义图表设计的 5 个原则:

  1. 数据映射:将数据值映射到像素坐标,确保比例准确
  2. 网格线辅助:水平网格线帮助用户读取数据值
  3. 标签清晰:坐标轴标签使用小字号,辅助阅读
  4. 颜色突出:数据点使用醒目的蓝色,网格线使用柔和的米色
  5. 容器统一:图表容器与其他卡片样式一致

10.2 萌宠日记体重图表总结

设计要素值说明
数据点5 个圆形,蓝色
网格线5 条水平,米色
Y 轴范围4.0-6.05 个标签
X 轴标签5 个与数据点对齐
图表高度180vp适中
容器白色卡片12vp 圆角

7.1 属性对比

属性类型必填默认值说明
widthLength否'100%'组件宽度
heightLength否自适应组件高度
paddingPadding否0内边距
marginMargin否0外边距
backgroundColorColor否透明背景颜色
borderRadiusLength否0圆角半径
shadowShadow否无阴影效果

总结

本文从萌宠日记的体重折线图实现出发,深入解析了使用 Stack 绘制自定义图表的完整方法:

  1. Stack 层叠:网格线背景 + 数据点前景叠加
  2. 网格线绘制:ForEach 渲染 5 条水平线
  3. 数据点绘制:Circle 组件 + position 定位
  4. 坐标轴标签:Y 轴 5 个标签,X 轴 5 个标签
  5. 图表标题:标题 + 单位说明
  6. 动态数据:用真实数据驱动图表渲染
  7. 折线连接:Path 组件绘制数据点之间的连线

使用基础组件绘制自定义图表,避免了引入第三方库的依赖,对于轻量级的数据可视化场景非常实用。

下一篇我们将深入Y 轴与 X 轴标签布局,解析图表坐标轴标签的精确对齐与布局设计。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • Stack 组件:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-stack
  • Circle 组件:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-circle
  • Path 组件:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-image
  • Row 组件:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-row
  • 数据可视化:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/data-visualization
  • 颜色使用规范:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/color-usage
  • 布局基础:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkui-layout
  • 动画开发:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-animation

相关新闻

  • LangGraph 深度解析:stream\_mode messages 与 values 核心区别(含HITL适配与代码实战)
  • 关于 springmvc 中的 ResponseBody 和 RequestBody 两个注解的差别
  • McBSP时钟停止模式配置SPI通信:原理、配置与实战指南

最新新闻

  • Anthropics细思极恐信任链崩塌了
  • stablecoin-evm安全特性详解:Blacklist与Pausable功能如何保障合约安全
  • 解决roslyn-linq-rewrite常见问题:NaN值处理与并行LINQ限制
  • 鸿蒙 ArkTS 实战:Water Bill Meter 从水费阶梯计算到生活缴费应用完整解析
  • PreMiD Activities元数据规范:创建符合标准的高质量状态插件
  • 从研发到上市踩坑无数?2026企业产品全周期第三方检测选型指南 - 互联网科技品牌测评

日新闻

  • AI云原生实战05-金融AI上云最难的不是技术,是“不出事“——TCE银行风控架构拆解
  • 2026年GEOSEO优化公司选型深度测评:五大硬核标准严选,这六家重塑搜索增长新格局 - 品牌前沿专家
  • **核验!2026年7月卡地亚香港**售后网点地址及服务电话公告 - 卡地亚服务中心

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号