HarmonyOS APP开发---"数据眼"健康追踪App,需要用到这个库
做一个健康追踪 App,每天的步数、心率、睡眠时长要用图表展示------自己用 Canvas 画图表?太累了。
@ohos/mpchart覆盖 7 大图表类型,手势缩放、数据高亮、自定义样式开箱即用。
📦 仓库地址:https://gitcode.com/CPF-ApplicationTPC/ohos_mpchart | 安装:ohpm install @ohos/mpchart
写在前面
"数据眼"是一个健康追踪 App,核心功能是把传感器采集的健康数据可视化:
- 步数走势:最近 7 天每天的步数 → 柱状图
- 心率曲线:今天 24 小时心率变化 → 折线图
- 睡眠分布:深睡/浅睡/清醒占比 → 饼状图
- 能力评估:心肺/力量/柔韧/平衡多维评分 → 雷达图
这些图表如果自己用 Canvas 画,每个都得写几百行:画轴、画网格、画数据点、处理手势缩放、处理点击高亮......4 种图表就是 2000+ 行代码。
@ohos/mpchart 提供了 7 大图表类型(线形/柱状/饼状/蜡烛/气泡/雷达/瀑布),自带手势交互和数据高亮,配置化使用,几十行就能出图。
这篇文章聊什么
- 步数柱状图------最近 7 天步数对比
- 心率折线图------24 小时心率曲线 + 缩放
- 睡眠饼状图------深睡/浅睡/清醒占比
#mermaid-svg-MpcXP7Oa32EVeK7c{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MpcXP7Oa32EVeK7c .error-icon{fill:#552222;}#mermaid-svg-MpcXP7Oa32EVeK7c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MpcXP7Oa32EVeK7c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MpcXP7Oa32EVeK7c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MpcXP7Oa32EVeK7c .marker.cross{stroke:#333333;}#mermaid-svg-MpcXP7Oa32EVeK7c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MpcXP7Oa32EVeK7c p{margin:0;}#mermaid-svg-MpcXP7Oa32EVeK7c .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster-label text{fill:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster-label span{color:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster-label span p{background-color:transparent;}#mermaid-svg-MpcXP7Oa32EVeK7c .label text,#mermaid-svg-MpcXP7Oa32EVeK7c span{fill:#333;color:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c .node rect,#mermaid-svg-MpcXP7Oa32EVeK7c .node circle,#mermaid-svg-MpcXP7Oa32EVeK7c .node ellipse,#mermaid-svg-MpcXP7Oa32EVeK7c .node polygon,#mermaid-svg-MpcXP7Oa32EVeK7c .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MpcXP7Oa32EVeK7c .rough-node .label text,#mermaid-svg-MpcXP7Oa32EVeK7c .node .label text,#mermaid-svg-MpcXP7Oa32EVeK7c .image-shape .label,#mermaid-svg-MpcXP7Oa32EVeK7c .icon-shape .label{text-anchor:middle;}#mermaid-svg-MpcXP7Oa32EVeK7c .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MpcXP7Oa32EVeK7c .rough-node .label,#mermaid-svg-MpcXP7Oa32EVeK7c .node .label,#mermaid-svg-MpcXP7Oa32EVeK7c .image-shape .label,#mermaid-svg-MpcXP7Oa32EVeK7c .icon-shape .label{text-align:center;}#mermaid-svg-MpcXP7Oa32EVeK7c .node.clickable{cursor:pointer;}#mermaid-svg-MpcXP7Oa32EVeK7c .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MpcXP7Oa32EVeK7c .arrowheadPath{fill:#333333;}#mermaid-svg-MpcXP7Oa32EVeK7c .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MpcXP7Oa32EVeK7c .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MpcXP7Oa32EVeK7c .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MpcXP7Oa32EVeK7c .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MpcXP7Oa32EVeK7c .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MpcXP7Oa32EVeK7c .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster text{fill:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c .cluster span{color:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MpcXP7Oa32EVeK7c .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MpcXP7Oa32EVeK7c rect.text{fill:none;stroke-width:0;}#mermaid-svg-MpcXP7Oa32EVeK7c .icon-shape,#mermaid-svg-MpcXP7Oa32EVeK7c .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MpcXP7Oa32EVeK7c .icon-shape p,#mermaid-svg-MpcXP7Oa32EVeK7c .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MpcXP7Oa32EVeK7c .icon-shape .label rect,#mermaid-svg-MpcXP7Oa32EVeK7c .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MpcXP7Oa32EVeK7c .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MpcXP7Oa32EVeK7c .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MpcXP7Oa32EVeK7c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步数
心率
睡眠
能力
传感器数据
数据处理
图表类型
BarChart 柱状图
LineChart 折线图
PieChart 饼状图
RadarChart 雷达图
手势缩放+点击高亮
渲染到 UI
第一步:安装
bash
ohpm install @ohos/mpchart
无需任何权限(纯渲染组件)。
第二步:步数柱状图------最近 7 天
typescript
import {
BarChart, BarChartModel, BarData, BarDataSet, BarEntry,
JArrayList, XAxis, XAxisPosition, YAxis, Description,
OnChartValueSelectedListener, Highlight, EntryOhos
} from '@ohos/mpchart'
@Entry
@Component
struct StepsChartPage {
private barChart: BarChart = new BarChart()
private model: BarChartModel = new BarChartModel()
aboutToAppear() {
// 模拟最近 7 天步数
const steps = [8234, 10245, 6789, 9876, 12034, 5678, 8901]
const days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
const entries = new JArrayList<BarEntry>()
steps.forEach((val, i) => entries.add(new BarEntry(i, val)))
const dataSet = new BarDataSet(entries, '每日步数')
dataSet.setColorByColor(0xFF4ECDC4) // 青绿色
const barData = new BarData(dataSet)
barData.setBarWidth(0.5)
this.model.setData(barData)
this.model.getXAxis().setPosition(XAxisPosition.BOTTOM)
this.model.getXAxis().setValueFormatter((value) => days[Math.floor(value)] || '')
this.model.getAxisLeft().setAxisMinimum(0)
this.model.getAxisRight().setEnabled(false) // 隐藏右侧 Y 轴
this.model.setDescription(new Description().setText('单位:步'))
// 点击柱子高亮
this.barChart.setOnChartValueSelectedListener({
onValueSelected: (e: EntryOhos, h: Highlight) => {
promptAction.showToast({
message: `${days[Math.floor(e.getX())]}: ${e.getY()} 步`,
})
},
onNothingSelected: () => {},
})
this.barChart.setModel(this.model)
}
build() {
Column() {
Text('本周步数').fontSize(20).fontWeight(FontWeight.Bold).padding(12)
this.barChart
}
.width('100%').height(400)
}
}
第三步:心率折线图------24 小时曲线
typescript
import {
LineChart, LineChartModel, LineData, LineDataSet, LineEntry,
JArrayList, XAxisPosition
} from '@ohos/mpchart'
// 24 小时心率数据(每小时一个点)
const heartRates = [62, 60, 58, 56, 55, 58, 64, 72, 80, 85, 78, 76,
74, 72, 70, 75, 82, 88, 92, 85, 76, 70, 66, 62]
const entries = new JArrayList<LineEntry>()
heartRates.forEach((hr, i) => entries.add(new LineEntry(i, hr)))
const dataSet = new LineDataSet(entries, '心率 (bpm)')
dataSet.setColorByColor(0xFFFF6B6B) // 红色曲线
dataSet.setCircleColor(0xFFFF6B6B)
dataSet.setLineWidth(2)
dataSet.setDrawFilled(true) // 曲线下方填充
dataSet.setFillColor(0x33FF6B6B)
const model = new LineChartModel()
model.setData(new LineData(dataSet))
model.getXAxis().setPosition(XAxisPosition.BOTTOM)
model.getXAxis().setValueFormatter((v) => `${Math.floor(v)}:00`)
model.getAxisLeft().setAxisMinimum(40)
model.getAxisRight().setEnabled(false)
model.setDescription(new Description().setText('24h 心率'))
// 支持手势缩放(双指缩放看细节)
model.setPinchZoom(true)
model.setDoubleTapToZoomEnabled(true)
第四步:睡眠饼状图------占比分布
typescript
import {
PieChart, PieChartModel, PieData, PieDataSet, PieEntry,
JArrayList
} from '@ohos/mpchart'
// 睡眠分布:深睡 2h、浅睡 5h、REM 1.5h、清醒 0.5h
const entries = new JArrayList<PieEntry>()
entries.add(new PieEntry(2, '深睡'))
entries.add(new PieEntry(5, '浅睡'))
entries.add(new PieEntry(1.5, 'REM'))
entries.add(new PieEntry(0.5, '清醒'))
const dataSet = new PieDataSet(entries, '睡眠分布')
dataSet.setColors([0xFF6C5CE7, 0xFF74B9FF, 0xFFFDCB6E, 0xFFFF7675])
dataSet.setSliceSpace(2) // 扇区间隙
const model = new PieChartModel()
model.setData(new PieData(dataSet))
model.setUsePercentValues(true) // 显示百分比
model.setDescription(new Description().setText(''))
为什么"数据眼"选了 mpchart?
| 需求 | 自研 Canvas | @ohos/mpchart |
|---|---|---|
| 柱状图 | 200+ 行 | 30 行 |
| 折线图 | 300+ 行 | 30 行 |
| 饼状图 | 250+ 行 | 20 行 |
| 手势缩放 | 手写 | ✅ 内置 |
| 点击高亮 | 手写 | ✅ 内置 |
| 雷达图 | 400+ 行 | 30 行 |
总结
"数据眼"这个场景里,@ohos/mpchart 解决了三件事:
- 多图表覆盖------柱状/折线/饼状/雷达,一个库搞定健康数据可视化全家桶
- 交互开箱即用------手势缩放、点击高亮、数据选中,不用手写
- 高度自定义------颜色、轴、网格、动画、格式化器,细节全可控
如果你也在做健康、金融、电商、IoT 监控等需要数据可视化的 App,@ohos/mpchart 让你的图表 UI 告别从零造轮子,几十行出图不是梦。