Files
tuiche/lib/pages/mh_page/component/easychart.dart
2025-07-19 17:52:39 +08:00

207 lines
7.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:ef/base/chart/drawer.dart';
import 'package:ef/base/chart/easychart.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
enum ChartDisplayMode { line, bar, both, dualBar }
class LineView extends StatelessWidget {
final List<ChartLables> xLabels;
final List<ChartLables> yLabels;
final double barWidth;
final int xCount;
final int yCount;
final List<Offset> points;
final ChartDisplayMode displayMode;
final List<String>? barColors;
final List<List<Offset>>? dualBarPoints;
final String? xUnit;
final List<String> tips;
final double bottomPadding;
const LineView({
super.key,
required this.xLabels,
required this.yLabels,
required this.xCount,
required this.yCount,
required this.points,
required this.barWidth,
required this.tips,
this.xUnit = '',
this.bottomPadding = 100,
this.displayMode = ChartDisplayMode.bar,
this.barColors, // 添加进构造函数
this.dualBarPoints,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (a, b) {
return Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
left: 43.rpx,
bottom: bottomPadding.rpx,
),
child: EasyChartView(
key: Key(DateTime.now().toString()),
size: Size(b.maxWidth, 220.rpx),
drawer: ChartDrawer(
xAxis: ChartAxis(
intent: 28,
entintent: 9,
labels: xLabels,
count: xCount,
),
yAxis: ChartAxis(
color: Colors.transparent,
isX: false,
intent: 0,
entintent: 45.rpx.toInt(),
labels: yLabels,
count: yCount,
),
ondrawer: (canvas, size, drawer) {
canvas.scale(1, -1);
ChartLables.drawText(
canvas,
xUnit!,
Offset(drawer.yAxis.labels.first.offset.dx,
-drawer.drawsize.height + 0),
style: TextStyle(
color: Color(0xFFFFFFFF).withOpacity(0.6),
fontSize: 18.rpx,
),
);
canvas.scale(1, -1);
// 虚线
for (var i = 1;
i < drawer.yAxis.labels.first.labels.length;
i++) {
drawer.drawHorizontalDashedLine(
canvas,
drawer.yAxis.labels.first.steps[i].dy,
drawer.drawsize.width,
dashWidth: 3,
dashSpace: 3,
paint: Paint()..color = Colors.grey,
);
}
if (displayMode == ChartDisplayMode.line ||
displayMode == ChartDisplayMode.both) {
drawer.drawcurveline(
canvas,
points,
Paint()
..color = Color(0xFF00C1AA)
..strokeWidth = 1.5,
);
drawer.drawpoints(
canvas,
points,
5,
Paint()..color = Color(0Xff00C1AA),
values: tips,
);
}
if (displayMode == ChartDisplayMode.bar ||
displayMode == ChartDisplayMode.both) {
for (var i = 0; i < points.length; i++) {
final offset = points[i];
// final color = (barColors != null && barColors!.length > i)
// ? barColors![i]
// : Colors.yellow.withAlpha(100 + i * 10); // 默认回退
drawer.drawBar(
canvas,
Offset(offset.dx, 0),
barWidth,
offset.dy,
Paint()
..color = barColors!.length == 0
? Colors.white
: stringToColor(barColors![i]),
value: tips[i],
);
}
}
if ((displayMode == ChartDisplayMode.dualBar ||
displayMode == ChartDisplayMode.both) &&
dualBarPoints != null) {
for (int i = 0; i < dualBarPoints!.length; i++) {
final List<Offset> bar = dualBarPoints![i];
if (bar.length < 3) continue;
final Offset deep = bar[0]; // 深睡:起点 -> deep.dy
final Offset light = bar[1]; // 浅睡:起点 -> light.dy
final Offset total = bar[2]; // 总睡眠:起点 -> total.dy
const String deepColor = "#21AD5D"; // 深睡
const String lightColor = "#45D989"; // 浅睡
const String remainColor = "#D3D3D3"; // 剩余
// 画深睡
if (deep.dy > 0) {
drawer.drawBar(
canvas,
Offset(deep.dx, 0),
barWidth,
deep.dy,
value: tips[i],
Paint()..color = stringToColor(deepColor),
);
}
// 画浅睡(从 deep.dy 开始)
final double lightHeight = light.dy - deep.dy;
if (lightHeight > 0) {
drawer.drawBar(
canvas,
Offset(light.dx, deep.dy),
barWidth,
lightHeight,
Paint()..color = stringToColor(lightColor),
);
}
// 判断是否需要画灰色剩余段和文字
final double remainHeight = total.dy - light.dy;
if (remainHeight > 0.01) {
// 灰色部分
drawer.drawBar(
canvas,
Offset(total.dx, light.dy),
barWidth,
remainHeight,
Paint()
..color =
stringToColor(remainColor).withOpacity(0.5),
);
}
// 若已满,不绘制灰色段、也不显示文字(不做任何处理)
}
}
},
),
onTips: (view, tips) => Container(
padding: EdgeInsets.all(16.rpx), // ✅ 容器内部边距,给文字留空间
decoration: BoxDecoration(
color: themeController.currentColor.sc5,
borderRadius: BorderRadius.circular(20.rpx),
),
alignment: Alignment.center,
child: Text(
tips,
style: TextStyle(
color: Color(0XFFFFFFFF), // 多了一个 F建议改成正确格式
fontSize: 20.rpx,
),
),
)));
});
}
}