Flutter 框架跨平台鸿蒙开发 - 重力感知
运行效果图重力感知是一款基于传感器技术的数据记录应用,通过模拟重力传感器记录一天的重力变化轨迹。应用将抽象的重力数据转化为直观的可视化图表,让用户能够看到地球引力在一天中的微妙变化。应用以深蓝色为主色调,象征宇宙与科技。界面设计现代感十足,采用深色主题营造科技氛围。通过轨道动画展示重力场的概念,将三轴加速度数据实时展示,帮助用户理解重力的本质。重力感知是一款基于传感器技术的数据记录应用,通过模拟重
重力感知应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图



1.1 应用简介
重力感知是一款基于传感器技术的数据记录应用,通过模拟重力传感器记录一天的重力变化轨迹。应用将抽象的重力数据转化为直观的可视化图表,让用户能够看到地球引力在一天中的微妙变化。
应用以深蓝色为主色调,象征宇宙与科技。界面设计现代感十足,采用深色主题营造科技氛围。通过轨道动画展示重力场的概念,将三轴加速度数据实时展示,帮助用户理解重力的本质。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 重力感知 | 实时显示重力数据 | 模拟传感器 |
| 轨道动画 | 重力场可视化 | CustomPaint绘制 |
| 三轴显示 | X/Y/Z轴加速度 | 数值展示 |
| 数据记录 | 记录重力轨迹 | Timer定时采集 |
| 历史查看 | 查看历史记录 | 列表展示 |
| 数据分析 | 统计分析重力数据 | 算法计算 |
1.3 重力数据说明
| 数据项 | 说明 | 单位 |
|---|---|---|
| X轴加速度 | 水平方向加速度 | m/s² |
| Y轴加速度 | 垂直方向加速度 | m/s² |
| Z轴加速度 | 深度方向加速度 | m/s² |
| 重力大小 | 合成加速度大小 | m/s² |
| 标准重力 | 地球标准重力加速度 | 9.80665 m/s² |
1.4 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 动画系统 | AnimationController | - |
| 图形绘制 | CustomPaint | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.5 项目结构
lib/
└── main_gravity_sensor.dart
├── GravitySensorApp # 应用入口
├── GravityData # 重力数据模型
├── GravitySession # 重力会话模型
├── GravitySensorHomePage # 主页面(底部导航)
├── _buildSensorPage # 感知页面
├── _buildHistoryPage # 历史页面
├── _buildAnalysisPage # 分析页面
├── OrbitPainter # 轨道绘制器
├── MiniGravityPainter # 迷你图表绘制器
└── DetailGravityPainter # 详情图表绘制器
二、设计理念
2.1 重力感知概念
2.2 重力场可视化
2.3 色彩体系
应用采用深蓝色为主色调:
| 颜色类型 | 色值 | RGB | 用途 |
|---|---|---|---|
| 主色 | #3F51B5 | 63,81,181 | 导航、按钮、强调 |
| 辅助色 | #5C6BC0 | 92,107,192 | 渐变、次要元素 |
| 背景1 | #0F0F1E | 15,15,30 | 主背景 |
| 背景2 | #1A1A2E | 26,26,46 | 卡片背景 |
| 背景3 | #16213E | 22,33,62 | 次背景 |
| X轴 | Red | - | X轴加速度 |
| Y轴 | Green | - | Y轴加速度 |
| Z轴 | Blue | - | Z轴加速度 |
2.4 重力数据流程
三、系统架构
3.1 整体架构图
3.2 类图设计
3.3 数据记录流程
四、核心功能实现
4.1 传感器模拟
模拟重力传感器数据:
void _startSimulation() {
Timer.periodic(const Duration(milliseconds: 100), (timer) {
if (!mounted) {
timer.cancel();
return;
}
final random = Random();
setState(() {
// 模拟三轴加速度
_currentX = (random.nextDouble() - 0.5) * 2;
_currentY = (random.nextDouble() - 0.5) * 2;
_currentZ = 9.8 + (random.nextDouble() - 0.5) * 0.5;
// 计算合成重力
_currentMagnitude = sqrt(
_currentX * _currentX +
_currentY * _currentY +
_currentZ * _currentZ,
);
});
});
}
4.2 轨道动画绘制
绘制重力场轨道动画:
class OrbitPainter extends CustomPainter {
final double progress;
final double magnitude;
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final baseRadius = size.width / 2 - 20;
// 绘制三层轨道
for (int i = 0; i < 3; i++) {
final orbitProgress = (progress + i * 0.33) % 1.0;
final radius = baseRadius - i * 30;
final angle = orbitProgress * 2 * pi;
// 绘制轨道圆
final paint = Paint()
..color = const Color(0xFF3F51B5).withValues(alpha: 0.3 - i * 0.1)
..style = PaintingStyle.stroke
..strokeWidth = 1;
canvas.drawCircle(center, radius, paint);
// 绘制轨道上的粒子
final dotX = center.dx + radius * cos(angle);
final dotY = center.dy + radius * sin(angle);
final dotPaint = Paint()
..color = const Color(0xFF3F51B5).withValues(alpha: 0.8)
..style = PaintingStyle.fill;
canvas.drawCircle(Offset(dotX, dotY), 4, dotPaint);
}
}
}
4.3 数据记录系统
记录重力轨迹:
void _startRecording() {
setState(() {
_isRecording = true;
_currentDataPoints = [];
_recordingStartTime = DateTime.now();
});
_recordingTimer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
setState(() {
_currentDataPoints.add(GravityData(
timestamp: DateTime.now(),
x: _currentX,
y: _currentY,
z: _currentZ,
magnitude: _currentMagnitude,
));
});
});
}
void _stopRecording() {
_recordingTimer?.cancel();
if (_currentDataPoints.isEmpty) {
setState(() {
_isRecording = false;
});
return;
}
// 计算统计数据
final magnitudes = _currentDataPoints.map((d) => d.magnitude).toList();
final session = GravitySession(
id: DateTime.now().millisecondsSinceEpoch.toString(),
startTime: _recordingStartTime!,
endTime: DateTime.now(),
dataPoints: List.from(_currentDataPoints),
avgMagnitude: magnitudes.reduce((a, b) => a + b) / magnitudes.length,
maxMagnitude: magnitudes.reduce(max),
minMagnitude: magnitudes.reduce(min),
);
setState(() {
_sessions.insert(0, session);
_isRecording = false;
_currentDataPoints = [];
});
}
4.4 重力曲线绘制
绘制重力变化曲线:
class DetailGravityPainter extends CustomPainter {
final List<GravityData> dataPoints;
void paint(Canvas canvas, Size size) {
if (dataPoints.isEmpty) return;
final paint = Paint()
..color = const Color(0xFF3F51B5)
..style = PaintingStyle.stroke
..strokeWidth = 2;
final path = Path();
final points = <Offset>[];
// 计算数据点位置
for (int i = 0; i < dataPoints.length; i++) {
final x = (i / (dataPoints.length - 1)) * size.width;
final y = size.height - ((dataPoints[i].magnitude - 9.5) / 1.0 * size.height);
points.add(Offset(x, y.clamp(0, size.height)));
}
// 绘制平滑曲线
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 controlPoint = Offset(
(prevPoint.dx + points[i].dx) / 2,
(prevPoint.dy + points[i].dy) / 2,
);
path.quadraticBezierTo(
prevPoint.dx, prevPoint.dy,
controlPoint.dx, controlPoint.dy,
);
}
}
canvas.drawPath(path, paint);
// 绘制填充渐变
final fillPaint = Paint()
..shader = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xFF3F51B5).withValues(alpha: 0.3),
const Color(0xFF3F51B5).withValues(alpha: 0.0),
],
).createShader(Rect.fromLTWH(0, 0, size.width, size.height))
..style = PaintingStyle.fill;
final fillPath = Path.from(path);
fillPath.lineTo(size.width, size.height);
fillPath.lineTo(0, size.height);
fillPath.close();
canvas.drawPath(fillPath, fillPaint);
}
}
五、UI设计规范
5.1 配色方案
应用采用深蓝色为主色调:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #3F51B5 (Indigo) | 导航、按钮、强调 |
| 辅助色 | #5C6BC0 | 渐变、次要元素 |
| 背景1 | #0F0F1E | 主背景 |
| 背景2 | #1A1A2E | 卡片背景 |
| 背景3 | #16213E | 次背景 |
5.2 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 24-28px | Bold | #FFFFFF |
| 重力数值 | 24px | Bold | #FFFFFF |
| 轴标签 | 14px | Bold | 动态颜色 |
| 数值显示 | 16-18px | Bold | #3F51B5 |
| 辅助文字 | 11-14px | Regular | 50-70% White |
5.3 组件规范
5.3.1 重力球体
╭─────────────╮
╱ ╭───────╮ ╲
│ ╱ 9.81 ╲ │
│ │ m/s² │ │
│ ╲ ╱ │
╲ ╰───────╯ ╱
╰─────────────╯
5.3.2 三轴显示
┌──────────────────────────────────┐
│ X Y Z │
│ ╭───╮ ╭───╮ ╭───╮ │
│ │0.5│ │-0.3│ │9.8│ │
│ ╰───╯ ╰───╯ ╰───╯ │
│ 红 绿 蓝 │
└──────────────────────────────────┘
5.3.3 重力曲线
┌────────────────────────────────────┐
│ │
│ ╱╲ ╱╲ │
│ ╱ ╲ ╱ ╲ ╱╲ │
│ ╱ ╲╱ ╲ ╱ ╲ │
│ ╱ ╲╱ ╲ │
│ │
└────────────────────────────────────┘
六、交互设计
6.1 数据记录流程
6.2 轨道动画机制
6.3 页面切换状态
七、数据分析
7.1 重力数据统计
| 统计项 | 计算方式 | 说明 |
|---|---|---|
| 平均重力 | 所有数据点的平均值 | 整体水平 |
| 最大重力 | 所有数据点的最大值 | 峰值 |
| 最小重力 | 所有数据点的最小值 | 谷值 |
| 波动范围 | 最大值 - 最小值 | 变化幅度 |
7.2 三轴数据分析
// X轴加速度:水平方向
_currentX = (random.nextDouble() - 0.5) * 2; // -1 到 1
// Y轴加速度:垂直方向
_currentY = (random.nextDouble() - 0.5) * 2; // -1 到 1
// Z轴加速度:深度方向(主要重力分量)
_currentZ = 9.8 + (random.nextDouble() - 0.5) * 0.5; // 约 9.55 到 10.05
// 合成重力
_currentMagnitude = sqrt(x*x + y*y + z*z);
7.3 重力分布分析
| 轴 | 正常范围 | 说明 |
|---|---|---|
| X轴 | -1 ~ 1 m/s² | 水平方向加速度 |
| Y轴 | -1 ~ 1 m/s² | 垂直方向加速度 |
| Z轴 | 9.5 ~ 10.0 m/s² | 主要重力分量 |
| 合成 | 9.5 ~ 10.2 m/s² | 总体重力大小 |
八、扩展功能规划
8.1 后续版本规划
8.2 功能扩展建议
8.2.1 真实传感器接入
接入真实重力传感器:
- 使用sensors_plus插件
- 获取真实加速度计数据
- 支持陀螺仪数据
- 实时数据流处理
8.2.2 地理位置关联
关联地理位置信息:
- GPS定位集成
- 海拔高度影响
- 地理位置标记
- 地图可视化
8.2.3 数据导出
支持多种格式导出:
- CSV格式导出
- JSON数据导出
- 图表图片导出
- 数据分析报告
九、注意事项
9.1 开发注意事项
-
传感器模拟:当前使用模拟数据,实际应用需接入真实传感器
-
动画性能:轨道动画需要优化性能
-
数据存储:大量数据点需要注意内存管理
-
状态管理:使用setState管理本地状态
9.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 轨道不显示 | CustomPaint未正确实现 | 检查OrbitPainter |
| 数据不更新 | Timer未启动 | 检查_startSimulation |
| 记录为空 | Timer未正确保存 | 检查_recordingTimer |
| 曲线不显示 | 数据点为空 | 检查dataPoints |
9.3 使用提示
🌍 重力感知使用小贴士 🌍
地球标准重力加速度约为 9.80665 m/s²。
重力会因地理位置和海拔而略有不同。
记录重力轨迹可以了解设备运动状态。
持续记录可以发现重力的微小变化。
提示:建议在静止状态下记录,数据更准确。
十、运行说明
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_gravity_sensor.dart --web-port 8127
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_gravity_sensor.dart
# 运行到Windows
flutter run -d windows -t lib/main_gravity_sensor.dart
# 代码分析
flutter analyze lib/main_gravity_sensor.dart
十一、总结
重力感知是一款基于传感器技术的数据记录应用,通过模拟重力传感器记录一天的重力变化轨迹。应用将抽象的重力数据转化为直观的可视化图表,让用户能够看到地球引力在一天中的微妙变化。
从技术实现来看,应用使用模拟数据模拟重力传感器,通过CustomPaint绘制轨道动画和重力曲线,使用Timer定时采集数据点,实现了完整的重力数据记录和分析系统。
从用户体验来看,应用提供直观的重力场可视化,通过轨道动画展示重力场的概念。三轴加速度实时显示,帮助用户理解重力的本质。重力曲线绘制,让用户看到重力的变化轨迹。
应用不仅是一个数据记录工具,更是一个科学教育平台。它提醒我们:地球标准重力加速度约为 9.80665 m/s²;重力会因地理位置和海拔而略有不同;记录重力轨迹可以了解设备运动状态;持续记录可以发现重力的微小变化。在科技与自然的交汇点,重力感知为我们提供了一种探索世界的新方式。
记录地球引力的轨迹
更多推荐




所有评论(0)