import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; class ChartData { final String name; final double value; ChartData({required this.name, required this.value}); } Widget buildChartTitle(BuildContext context, String title, IconData icon) { return Row( children: [ Icon(icon, color: Theme.of(context).colorScheme.primary), Text(title), ], ); } Widget buildChartDivider(BuildContext context) { return Divider( height: 1, thickness: 1, color: Theme.of(context).colorScheme.primary, indent: 0, endIndent: 0, ); } Widget lineChart({ required BuildContext context, required String xAxisName, required String yAxisName, required String unit, required List data, }) { return SfCartesianChart( // 图表标题 // title: ChartTitle(text: '2023年上半年销售额(万元)'), // X轴配置(类别轴) primaryXAxis: CategoryAxis(majorGridLines: MajorGridLines(width: 0)), // Y轴配置(数值轴) // primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')), // 启用图例 legend: Legend(isVisible: true, position: LegendPosition.top), // 启用交互提示(点击数据点显示详情) tooltipBehavior: TooltipBehavior( enable: true, format: 'point.x: point.y $unit', ), // 折线图数据系列 series: [ LineSeries( dataSource: data, // X轴数据映射 xValueMapper: (ChartData chart, _) => chart.name, // Y轴数据映射 yValueMapper: (ChartData chart, _) => chart.value, // 线条颜色 color: Theme.of(context).colorScheme.primary, // 线条宽度 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 data, }) { return SfCartesianChart( // X轴配置(类别轴) primaryXAxis: CategoryAxis(majorGridLines: MajorGridLines(width: 0)), // Y轴配置(数值轴) // primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')), // 启用交互提示 tooltipBehavior: TooltipBehavior( enable: true, format: 'point.x: point.y $unit', ), // 柱状图数据系列 series: [ ColumnSeries( dataSource: data, // X轴数据映射 xValueMapper: (ChartData chart, _) => chart.name, // Y轴数据映射 yValueMapper: (ChartData chart, _) => chart.value, // 名称 name: yAxisName, // 柱子颜色 color: Theme.of(context).colorScheme.primary, // 柱子宽度(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 doubleBarChart({ required BuildContext context, required String xAxisName, required String yAxisName, required String unit, required List data1, required List data2, required String series1Name, required String series2Name, }) { return SfCartesianChart( // X轴配置(类别轴) primaryXAxis: CategoryAxis(majorGridLines: const MajorGridLines(width: 0)), // Y轴配置(数值轴) // primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')), // 图例配置 legend: Legend( isVisible: true, position: LegendPosition.top, overflowMode: LegendItemOverflowMode.wrap, ), // 启用交互提示 tooltipBehavior: TooltipBehavior( enable: true, format: 'series.name: point.y $unit', ), // 双柱状图数据系列 series: >[ ColumnSeries( dataSource: data1, // X轴数据映射 xValueMapper: (ChartData chart, _) => chart.name, // Y轴数据映射 yValueMapper: (ChartData chart, _) => chart.value, // 系列名称 name: series1Name, // 柱子颜色 color: Theme.of(context).colorScheme.primary, // 柱子宽度 width: 0.3, // 柱子边框 borderWidth: 1, borderColor: Colors.black12, // 数据标签 dataLabelSettings: const DataLabelSettings( isVisible: true, color: Colors.white, opacity: 0, alignment: ChartAlignment.center, ), // 动画效果 animationDuration: 2000, ), ColumnSeries( dataSource: data2, // X轴数据映射 xValueMapper: (ChartData chart, _) => chart.name, // Y轴数据映射 yValueMapper: (ChartData chart, _) => chart.value, // 系列名称 name: series2Name, // 柱子颜色 color: Theme.of(context).colorScheme.inversePrimary, // 柱子宽度 width: 0.3, // 柱子边框 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 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( 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, ), ], ); }