import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_habit/common/I18N.dart'; import 'package:flutter_habit/common/utils/ConvertUtils.dart'; class DateValueSingleLineChart extends StatelessWidget { final List sports; final int? size; final bool isEndYesterday; DateValueSingleLineChart({ required this.sports, this.size, this.isEndYesterday = false, }); @override Widget build(BuildContext context) { double? maxY, minY, maxX, minX, xInterval, yInterval; if (sports.isNotEmpty) { double now = ConvertUtils.localDaysSinceEpoch(isEndYesterday ? DateTime.now().subtract(Duration(days: 1)) : DateTime.now()) .floorToDouble(); maxX = now; minX = now - size!; maxY = sports[0].y; minY = sports[0].y; sports.forEach((i) { if (i.y < minY!) { minY = i.y; } if (i.y > maxY!) { maxY = i.y; } }); if (maxY == minY) { maxY = maxY! + 10; minY = minY! - 10; } else { double height = maxY! - minY!; maxY = maxY! + height; minY = minY! - height; if (minY! < 0) { maxY = maxY! + minY!; minY = 0; } } switch (size) { case 7: xInterval = 1; break; case 30: xInterval = 5; break; case 90: xInterval = 18; break; default: xInterval = 1; break; } yInterval = ((maxY! - minY!) / 6); } return sports.isEmpty ? Container( child: Column( children: [ Text( I18N.of("无数据"), style: Theme.of(context) .textTheme .displaySmall! .copyWith(color: Theme.of(context).colorScheme.secondary), ), Divider(), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( I18N.of("添加数据后会展示对应图表"), style: Theme.of(context).textTheme.bodySmall, ), ], ), ], )) : Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( height: 250, padding: EdgeInsets.only(top: 20, left: 10, right: 20), child: LineChart( LineChartData( // clipToBorder: true, // 边框信息 borderData: FlBorderData( show: true, border: Border.all( color: Theme.of(context).colorScheme.secondary, width: 1, ), ), gridData: FlGridData( show: true, drawVerticalLine: true, drawHorizontalLine: false, // 从左到右每隔几个整数数据画条竖线 verticalInterval: xInterval, // 横向网格线 getDrawingHorizontalLine: (value) { return FlLine( color: Theme.of(context).colorScheme.secondary, strokeWidth: 0.5, ); }, horizontalInterval: yInterval, // 纵向网格线 getDrawingVerticalLine: (value) { return FlLine( color: Theme.of(context).colorScheme.secondary, strokeWidth: 1, ); }, ), // 点击响应信息 lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( tooltipBgColor: Theme.of(context) .colorScheme .secondary .withOpacity(0.2) .withAlpha(100), fitInsideHorizontally: true, ), ), titlesData: FlTitlesData( show: true, // 下方文字 bottomTitles: AxisTitles( // 每隔几个显示一个底部标签 // interval: xInterval, // showTitles: true, // 文字与图表上边界距离 // margin: 8, // 文字预留空间 // reservedSize: 22, // textStyle: Theme.of(context).textTheme.bodyMedium, // getTitles: (value) { // DateTime dateTime = // ConvertUtils.dateTimeOfLocalDaysSinceEpoch(value); // return "${dateTime.month}-${dateTime.day}"; // }, ), leftTitles: AxisTitles( // 每隔几个显示一个左侧标签 // interval: yInterval, // showTitles: true, // 文字与图表左边界距离 // margin: 8, // 文字预留空间 // reservedSize: ConvertUtils.fixedDouble(maxY, 1) // .toString() // .length * // 6.5, // rotateAngle: -20, // textStyle: Theme.of(context).textTheme.bodyMedium, // getTitles: (value) { // return ConvertUtils.fixedDouble(value, 1).toString(); // }, ), ), // 各轴显示的最值 (不设置则缩放) minX: minX, maxX: maxX, maxY: maxY, minY: minY, // 数据 lineBarsData: [ LineChartBarData( spots: sports, // 圆滑 isCurved: size! > 7, // 线条颜色 color: Theme.of(context).colorScheme.secondary, // 线条宽度 barWidth: 3, // 起点和终点是否圆滑 isStrokeCapRound: true, // 点配置 dotData: FlDotData( show: size! < 30, // getDotColor: (spot, percent, barData) => // Theme.of(context).colorScheme.secondary, // dotSize: 3, ), // 线下方填充 belowBarData: BarAreaData( show: true, color: Theme.of(context) .colorScheme .secondary .withOpacity(0.3) , ), ), ], ), ), ), ], ); } }