Flutter 睡眠时长图表组件开发详解
Github 地址:https://github.com/Azad-Zhang/sleep_chart
Pub.dev 地址:https://pub.dev/packages/sleep_chart
1. 项目背景
睡眠时长图表是一个用于展示用户睡眠数据的可视化组件,它能够清晰地展示不同睡眠阶段(浅睡、深睡、快速眼动等)的分布情况。本文将详细介绍如何从零开始实现这个组件。
预览图打不开请打开VPN,并在Github查看,因为图是放在Github上的。
2. 项目结构
首先,让我们了解项目的基本结构:
lib/
├── src/
│ └── sleep_chart_page.dart // 主要实现文件
└── sleep_chart.dart // 导出文件
3. 核心实现
3.1 数据模型定义
首先,我们需要定义几个核心的数据模型:
// 睡眠阶段枚举
enum SleepStage {
light, // 浅睡
deep, // 深睡
awake, // 清醒
notWorn, // 未佩戴
rem, // 快速眼动
unknown // 未知状态
}
// 睡眠详情数据类
class SleepDetailChart {
final SleepStage model; // 睡眠阶段
final double width; // 宽度
final DateTime startTime; // 开始时间
final DateTime endTime; // 结束时间
final int duration; // 持续时间(分钟)
SleepDetailChart({
required this.model,
required this.width,
required this.startTime,
required this.endTime,
required this.duration,
});
}
3.2 样式定义
为了支持自定义样式,我们定义了以下样式类:
// 线条样式
class LineStyle {
final double width; // 线条宽度
final double space; // 线条间距
const LineStyle({
required this.width,
required this.space,
});
}
// 画笔样式
class PaintStyle {
final Color color;
final double strokeWidth;
final PaintingStyle style;
final StrokeCap strokeCap;
const PaintStyle({
required this.color,
required this.strokeWidth,
required this.style,
required this.strokeCap,
});
}
// 睡眠阶段样式
class SleepStageStyle {
final List<Color>? gradientColor; // 渐变色
final Color? color; // 纯色
final SleepStageStyleValue value; // 样式值
SleepStageStyle({
this.gradientColor,
this.color,
required this.value,
});
}
3.3 自定义绘制器实现
核心绘制逻辑在 SleepDurationPainter
类中实现:
class SleepDurationPainter extends CustomPainter {
// 构造函数
SleepDurationPainter({
required this.heightUnit,
required this.titleHeight,
required this.titleGap,
required this.xAxisTitleOffset,
required this.xAxisTitleHeight,
required this.bgColor,
required this.details,
required this.startTime,
required this.endTime,
this.horizontalLineStyle = const LineStyle(width: 5.0, space: 3.0),
this.verticalLineStyle = const LineStyle(width: 5.0, space: 3.0),
this.horizontalLineCount = 8,
this.dividerPaintStyle = const PaintStyle(
color: Color(0xFFEEEEEE