Flutter 框架跨平台鸿蒙开发 - 人生心电图
人生心电图应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
人生心电图是一款独特的数据可视化应用,将用户的情绪、睡眠、运动等生活数据绘制成一条"生命线"。通过心电图式的曲线展示,让用户直观地看到自己生活的起伏变化,更好地了解和管理自己的生活质量。
应用以青色为主色调,象征生命与活力。界面设计简洁现代,采用深色主题营造专业感。通过CustomPaint绘制心电图曲线,将抽象的生活数据转化为直观的视觉呈现,帮助用户发现生活中的规律和趋势。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 心电图展示 | 生命线可视化 | CustomPaint绘制 |
| 数据记录 | 记录六维生活数据 | 滑块输入 |
| 类型切换 | 切换不同数据类型 | 选择器组件 |
| 趋势分析 | 数据趋势分析 | 统计算法 |
| 数据分布 | 各维度数据分布 | 进度条展示 |
| 生活洞察 | 智能生活建议 | 规则引擎 |
1.3 生活数据类型
应用追踪六大生活维度:
| 数据类型 | 图标 | 颜色 | 说明 |
|---|---|---|---|
| 情绪 | sentiment_satisfied | #E91E63 | 情绪状态和心情 |
| 睡眠 | bedtime | #9C27B0 | 睡眠质量和时长 |
| 运动 | directions_run | #4CAF50 | 运动量和强度 |
| 工作 | work | #FF9800 | 工作效率和压力 |
| 社交 | people | #2196F3 | 社交活动和互动 |
| 健康 | favorite | #F44336 | 身体健康状况 |
1.4 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 图形绘制 | CustomPaint | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.5 项目结构
lib/
└── main_life_ecg.dart
├── LifeEcgApp # 应用入口
├── LifeDataType # 生活数据类型枚举
├── LifeDataPoint # 数据点模型
├── LifeEcgRecord # 心电图记录模型
├── LifeEcgHomePage # 主页面(底部导航)
├── _buildEcgPage # 心电图页面
├── _buildRecordPage # 记录页面
├── _buildAnalysisPage # 分析页面
└── EcgPainter # 心电图绘制器
二、设计理念
2.1 生命线概念
2.2 数据可视化理念
2.3 色彩体系
应用采用青色为主色调:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #00BCD4 (Cyan) | 导航、按钮、强调 |
| 辅助色 | #0097A7 (Dark Cyan) | 渐变、次要元素 |
| 情绪 | #E91E63 (Pink) | 情绪数据 |
| 睡眠 | #9C27B0 (Purple) | 睡眠数据 |
| 运动 | #4CAF50 (Green) | 运动数据 |
| 工作 | #FF9800 (Orange) | 工作数据 |
| 社交 | #2196F3 (Blue) | 社交数据 |
| 健康 | #F44336 (Red) | 健康数据 |
2.4 数值评估体系
| 数值范围 | 等级 | 颜色 | 说明 |
|---|---|---|---|
| 0-30 | 低 | 红色 | 需要关注和改善 |
| 31-70 | 中 | 橙色 | 正常水平 |
| 71-100 | 高 | 绿色 | 良好状态 |
三、系统架构
3.1 整体架构图
3.2 类图设计
3.3 数据流程时序图
四、核心功能实现
4.1 心电图绘制
心电图绘制是应用的核心功能:
class EcgPainter extends CustomPainter {
final List<LifeEcgRecord> records;
final LifeDataType selectedType;
void paint(Canvas canvas, Size size) {
if (records.isEmpty) return;
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..strokeCap = StrokeCap.round;
final path = Path();
final points = <Offset>[];
// 计算数据点位置
for (int i = 0; i < records.length; i++) {
final x = (i / (records.length - 1)) * size.width;
final value = records[i].values[selectedType] ?? 50;
final y = size.height - (value / 100 * size.height * 0.8) - 20;
points.add(Offset(x, y));
}
// 绘制平滑曲线
for (int i = 0; i < points.length; i++) {
if (i == 0) {
path.moveTo(points[i].dx, points[i].dy);
} else {
final prevPoint = points[i - 1];
final currentPoint = points[i];
final controlPoint = Offset(
(prevPoint.dx + currentPoint.dx) / 2,
(prevPoint.dy + currentPoint.dy) / 2,
);
path.quadraticBezierTo(
prevPoint.dx, prevPoint.dy,
controlPoint.dx, controlPoint.dy,
);
}
}
// 绘制曲线
canvas.drawPath(path, paint);
// 绘制数据点
for (int i = 0; i < points.length; i++) {
final point = points[i];
final value = records[i].values[selectedType] ?? 50;
// 根据数值确定颜色
Color pointColor;
if (value < 30) {
pointColor = Colors.red;
} else if (value < 70) {
pointColor = Colors.orange;
} else {
pointColor = Colors.green;
}
// 绘制数据点
final circlePaint = Paint()
..color = pointColor
..style = PaintingStyle.fill;
canvas.drawCircle(point, 4, circlePaint);
}
}
}
4.2 数据记录系统
六维数据记录系统:
Widget _buildValueSlider(LifeDataType type) {
final value = _currentValues[type] ?? 50;
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.05),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: type.color.withValues(alpha: 0.3),
),
),
child: Column(
children: [
// 类型标签和数值显示
Row(
children: [
Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: type.color.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(10),
),
child: Icon(type.icon, color: type.color),
),
const SizedBox(width: 12),
Expanded(
child: Text(type.label),
),
Container(
child: Text('$value'),
),
],
),
// 滑块
Slider(
value: value.toDouble(),
min: 0,
max: 100,
divisions: 100,
onChanged: (newValue) {
setState(() {
_currentValues[type] = newValue.round();
});
},
),
],
),
);
}
4.3 趋势分析算法
计算各维度的趋势:
Map<LifeDataType, String> _calculateTrends() {
final trends = <LifeDataType, String>{};
if (_records.length < 2) {
for (var type in LifeDataType.values) {
trends[type] = '稳定';
}
return trends;
}
// 分割数据:最近7天 vs 之前的数据
final recent = _records.skip(_records.length - 7).toList();
final earlier = _records.take(_records.length - 7).toList();
for (var type in LifeDataType.values) {
// 计算最近平均值
final recentAvg = recent.isEmpty
? 0.0
: recent.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) / recent.length;
// 计算之前平均值
final earlierAvg = earlier.isEmpty
? 0.0
: earlier.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) / earlier.length;
// 计算差异
final diff = recentAvg - earlierAvg;
// 判断趋势
if (diff > 5) {
trends[type] = '上升';
} else if (diff < -5) {
trends[type] = '下降';
} else {
trends[type] = '稳定';
}
}
return trends;
}
4.4 平均值计算
计算各维度的平均值:
Map<LifeDataType, double> _calculateAverageValues() {
final avgValues = <LifeDataType, double>{};
for (var type in LifeDataType.values) {
final sum = _records.fold<int>(
0,
(sum, record) => sum + (record.values[type] ?? 0),
);
avgValues[type] = _records.isEmpty ? 0 : sum / _records.length;
}
return avgValues;
}
五、UI设计规范
5.1 配色方案
应用采用青色为主色调:
| 颜色类型 | 色值 | RGB | 用途 |
|---|---|---|---|
| 主色 | #00BCD4 | 0,188,212 | 导航、按钮 |
| 辅助色 | #0097A7 | 0,151,167 | 渐变、次要元素 |
| 情绪 | #E91E63 | 233,30,99 | 情绪数据 |
| 睡眠 | #9C27B0 | 156,39,176 | 睡眠数据 |
| 运动 | #4CAF50 | 76,175,80 | 运动数据 |
| 工作 | #FF9800 | 255,152,0 | 工作数据 |
| 社交 | #2196F3 | 33,150,243 | 社交数据 |
| 健康 | #F44336 | 244,67,54 | 健康数据 |
5.2 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 24-28px | Bold | #FFFFFF |
| 卡片标题 | 18px | Bold | #FFFFFF |
| 数据标签 | 13-16px | Medium | 70% White |
| 数值显示 | 16-20px | Bold | 动态颜色 |
| 辅助文字 | 11-14px | Regular | 40-60% White |
5.3 组件规范
5.3.1 心电图展示
┌─────────────────────────────────────────────┐
│ 生命线 最近30天 │
│ │
│ ╱╲ ╱╲ │
│ ╱ ╲ ╱ ╲ ╱╲ │
│ ╱╲ ╱ ╲ ╱ ╲ ╱ ╲ │
│ ╱ ╲ ╲╱ ╲╱ ╲ │
│ ╱ ╲ │
│ ╱ ╲ │
│ │
│ 1/1 1/30 │
└─────────────────────────────────────────────┘
5.3.2 数据滑块
┌─────────────────────────────────────────────┐
│ 😊 情绪 75 │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ 低 高 │
└─────────────────────────────────────────────┘
5.3.3 趋势标签
┌─────────────────────────────────────────────┐
│ 😊 情绪 ↗ 上升 │
│ 😴 睡眠 → 稳定 │
│ 🏃 运动 ↘ 下降 │
└─────────────────────────────────────────────┘
六、交互设计
6.1 数据记录流程
6.2 心电图查看流程
6.3 页面切换状态
七、数据分析
7.1 数据采集维度
六大生活数据维度:
| 维度 | 说明 | 评估指标 |
|---|---|---|
| 情绪 | 心情状态和情绪波动 | 愉悦度、稳定性 |
| 睡眠 | 睡眠质量和时长 | 深度、时长、质量 |
| 运动 | 运动量和强度 | 频率、强度、时长 |
| 工作 | 工作效率和压力 | 效率、压力、满意度 |
| 社交 | 社交活动和互动 | 频率、质量、满意度 |
| 健康 | 身体健康状况 | 体能、状态、舒适度 |
7.2 趋势分析方法
7.3 健康度计算
综合健康度评分算法:
int _calculateHealthScore(Map<LifeDataType, double> avgValues) {
// 计算所有维度的平均值
final avg = avgValues.values.reduce((a, b) => a + b) / avgValues.length;
// 返回整数分数
return avg.round();
}
7.4 数据分布分析
各维度数据分布统计:
// 计算各维度的平均值
for (var type in LifeDataType.values) {
final avg = _records.isEmpty
? 0.0
: _records.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) /
_records.length;
// 显示进度条
LinearProgressIndicator(
value: avg / 100,
backgroundColor: Colors.white.withValues(alpha: 0.1),
valueColor: AlwaysStoppedAnimation<Color>(type.color),
);
}
八、扩展功能规划
8.1 后续版本规划
8.2 功能扩展建议
8.2.1 数据导出
支持多种格式导出:
- CSV格式导出
- PDF报告生成
- 图片分享
- 数据备份
8.2.2 智能提醒
基于数据的智能提醒:
- 数据记录提醒
- 异常数据警告
- 趋势变化提醒
- 健康建议推送
8.2.3 AI分析
人工智能数据分析:
- 异常检测
- 模式识别
- 预测分析
- 个性化建议
九、注意事项
9.1 开发注意事项
-
数据绘制:CustomPaint需要正确计算坐标
-
性能优化:大量数据点时注意性能
-
状态管理:使用setState管理本地状态
-
用户体验:保持界面简洁,避免信息过载
9.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 曲线不显示 | 数据为空 | 检查records |
| 数据点位置错误 | 坐标计算错误 | 检查paint方法 |
| 颜色不正确 | 颜色逻辑错误 | 检查颜色判断 |
| 趋势分析错误 | 算法问题 | 检查计算逻辑 |
9.3 使用提示
📊 人生心电图使用小贴士 📊
每天记录,持续追踪。
关注趋势,发现规律。
平衡生活,关注健康。
数据驱动,科学决策。
提示:建议每天固定时间记录,保持数据的连续性。
十、运行说明
10.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
10.2 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_life_ecg.dart --web-port 8126
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_life_ecg.dart
# 运行到Windows
flutter run -d windows -t lib/main_life_ecg.dart
# 代码分析
flutter analyze lib/main_life_ecg.dart
十一、总结
人生心电图是一款独特的数据可视化应用,将用户的情绪、睡眠、运动等生活数据绘制成一条"生命线"。通过心电图式的曲线展示,让用户直观地看到自己生活的起伏变化,更好地了解和管理自己的生活质量。
从技术实现来看,应用使用CustomPaint绘制心电图曲线,将抽象的生活数据转化为直观的视觉呈现。通过六维数据记录系统,全面追踪用户的生活状态。采用趋势分析算法,帮助用户发现生活中的规律和趋势。
从用户体验来看,应用提供简洁直观的界面,让用户轻松记录和查看数据。通过颜色编码和趋势标签,让用户快速理解数据含义。提供生活洞察建议,帮助用户改善生活质量。
应用不仅是一个数据记录工具,更是一个生活管理平台。它提醒我们:每天记录,持续追踪;关注趋势,发现规律;平衡生活,关注健康;数据驱动,科学决策。在快节奏的现代生活中,人生心电图为我们提供了一种科学管理生活的方式。
记录生命的每一次跳动
更多推荐

所有评论(0)