feat:更新统计模块
This commit is contained in:
183
lib/widgets/common/chart.dart
Normal file
183
lib/widgets/common/chart.dart
Normal file
@@ -0,0 +1,183 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:food_hub_app/models/stats.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
Widget lineChart({
|
||||
required BuildContext context,
|
||||
required String xAxisName,
|
||||
required String yAxisName,
|
||||
required String unit,
|
||||
required List<ChartData> data,
|
||||
}) {
|
||||
return SfCartesianChart(
|
||||
// 图表标题
|
||||
// title: ChartTitle(text: '2023年上半年销售额(万元)'),
|
||||
|
||||
// X轴配置(类别轴)
|
||||
primaryXAxis: CategoryAxis(majorGridLines: MajorGridLines(width: 0)),
|
||||
|
||||
// Y轴配置(数值轴)
|
||||
// primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')),
|
||||
|
||||
// 启用图例
|
||||
// legend: const Legend(isVisible: true),
|
||||
|
||||
// 启用交互提示(点击数据点显示详情)
|
||||
tooltipBehavior: TooltipBehavior(
|
||||
enable: true,
|
||||
format: 'point.x: point.y $unit',
|
||||
),
|
||||
|
||||
// 折线图数据系列
|
||||
series: [
|
||||
LineSeries<ChartData, String>(
|
||||
dataSource: data,
|
||||
// X轴数据映射
|
||||
xValueMapper: (ChartData chart, _) => chart.name,
|
||||
// Y轴数据映射
|
||||
yValueMapper: (ChartData chart, _) => chart.value,
|
||||
// 线条颜色
|
||||
color: Theme.of(context).primaryColor,
|
||||
// 线条宽度
|
||||
width: 3,
|
||||
|
||||
// 数据点样式
|
||||
markerSettings: const MarkerSettings(
|
||||
isVisible: true,
|
||||
color: Colors.white,
|
||||
shape: DataMarkerType.circle,
|
||||
height: 6,
|
||||
width: 6,
|
||||
),
|
||||
|
||||
// 折线名称(会显示在图例中)
|
||||
name: yAxisName,
|
||||
|
||||
// 启用数据标签(直接显示数值)
|
||||
dataLabelSettings: const DataLabelSettings(
|
||||
isVisible: true,
|
||||
color: Colors.white,
|
||||
opacity: 0,
|
||||
),
|
||||
|
||||
// 动画效果
|
||||
animationDuration: 2000, // 动画时长(毫秒)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget barChart({
|
||||
required BuildContext context,
|
||||
required String xAxisName,
|
||||
required String yAxisName,
|
||||
required String unit,
|
||||
required List<ChartData> data,
|
||||
}) {
|
||||
return SfCartesianChart(
|
||||
// X轴配置(类别轴)
|
||||
primaryXAxis: CategoryAxis(
|
||||
majorGridLines: MajorGridLines(width: 0),
|
||||
title: AxisTitle(text: xAxisName),
|
||||
),
|
||||
|
||||
// Y轴配置(数值轴)
|
||||
primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')),
|
||||
|
||||
// 启用交互提示
|
||||
tooltipBehavior: TooltipBehavior(
|
||||
enable: true,
|
||||
format: 'point.x: point.y $unit',
|
||||
),
|
||||
|
||||
// 柱状图数据系列
|
||||
series: [
|
||||
ColumnSeries<ChartData, String>(
|
||||
dataSource: data,
|
||||
// X轴数据映射
|
||||
xValueMapper: (ChartData chart, _) => chart.name,
|
||||
// Y轴数据映射
|
||||
yValueMapper: (ChartData chart, _) => chart.value,
|
||||
|
||||
// 名称
|
||||
name: yAxisName,
|
||||
|
||||
// 柱子颜色
|
||||
color: Theme.of(context).primaryColor,
|
||||
|
||||
// 柱子宽度(0-1之间,1表示占满类别间隔)
|
||||
width: 0.6,
|
||||
|
||||
// 柱子边框
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.black12,
|
||||
|
||||
// 数据标签
|
||||
dataLabelSettings: const DataLabelSettings(
|
||||
isVisible: true,
|
||||
color: Colors.white,
|
||||
opacity: 0,
|
||||
alignment: ChartAlignment.center,
|
||||
),
|
||||
|
||||
// 动画效果
|
||||
animationDuration: 2000,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget pieChart({
|
||||
required BuildContext context,
|
||||
required String unit,
|
||||
required List<ChartData> data,
|
||||
}) {
|
||||
// 计算 value 的总和
|
||||
double sumValue = data.fold(0.0, (sum, item) => sum + item.value);
|
||||
|
||||
return SfCircularChart(
|
||||
// 饼图标题
|
||||
// title: ChartTitle(text: '菜谱类别占比分布'),
|
||||
|
||||
// 启用图例
|
||||
legend: const Legend(isVisible: true, position: LegendPosition.right),
|
||||
|
||||
// 启用交互提示(点击扇区显示详情)
|
||||
tooltipBehavior: TooltipBehavior(
|
||||
enable: true,
|
||||
format: 'point.x: point.y $unit',
|
||||
),
|
||||
|
||||
// 饼图系列配置
|
||||
series: [
|
||||
PieSeries<ChartData, String>(
|
||||
dataSource: data,
|
||||
// 类别映射(饼图扇区名称)
|
||||
xValueMapper: (ChartData data, _) => data.name,
|
||||
// 数值映射(扇区大小占比)
|
||||
yValueMapper: (ChartData data, _) => data.value,
|
||||
|
||||
// 扇区半径(0-1之间,1表示充满容器)
|
||||
// radius: '50%',
|
||||
|
||||
// 启用扇区分离效果
|
||||
explode: true,
|
||||
// 指定分离的扇区索引(这里分离第一个扇区)
|
||||
explodeIndex: 0,
|
||||
// 分离距离
|
||||
explodeOffset: '5%',
|
||||
|
||||
dataLabelMapper: (ChartData data, _) {
|
||||
final percentage = (data.value / sumValue * 100).toStringAsFixed(0);
|
||||
return '$percentage%';
|
||||
},
|
||||
|
||||
// 数据标签(显示在扇区上的文本)
|
||||
dataLabelSettings: DataLabelSettings(isVisible: true),
|
||||
|
||||
// 动画效果
|
||||
animationDuration: 2000,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user