Flutter graphic库堆叠柱状图8月16日显示异常排查求助
Flutter graphic库堆叠柱状图单类型日期柱形显示异常问题
问题场景
在Web项目中使用Flutter 3.7.10和graphic ^2.2.0实现堆叠柱状图时,发现8月16日仅存在Type 3数据的柱形显示异常。仅使用两类数据(如Type1+Type2)时图表显示正常,尝试过重新排序日期、为缺失类型补充空值(value=0),但问题仍未解决。
问题原因
核心原因是StackModifier在计算堆叠位置时,依赖同一日期下所有类型的数据元组做基准计算。当某一日期只有单个类型数据时,缺少其他类型的空值元组会导致堆叠逻辑的起点判断异常,无法正确从y=0开始绘制柱形。
解决方案
补全所有日期下的全类型数据,缺失类型的value设为0,确保每个日期都包含所有类型的数据项,让StackModifier能正确计算堆叠基准。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:graphic/graphic.dart'; class MyWidget extends StatelessWidget { const MyWidget({super.key}); @override Widget build(BuildContext context) { // 补全所有日期的全类型数据,缺失项value设为0 final data = [ // 8月11日 {'id': DateTime(2023, 8, 11), 'type': 'Type 1', 'value': 2}, {'id': DateTime(2023, 8, 11), 'type': 'Type 2', 'value': 2}, {'id': DateTime(2023, 8, 11), 'type': 'Type 3', 'value': 0}, // 8月14日 {'id': DateTime(2023, 8, 14), 'type': 'Type 1', 'value': 4}, {'id': DateTime(2023, 8, 14), 'type': 'Type 2', 'value': 4}, {'id': DateTime(2023, 8, 14), 'type': 'Type 3', 'value': 0}, // 8月16日 {'id': DateTime(2023, 8, 16), 'type': 'Type 1', 'value': 0}, {'id': DateTime(2023, 8, 16), 'type': 'Type 2', 'value': 0}, {'id': DateTime(2023, 8, 16), 'type': 'Type 3', 'value': 1}, // 8月18日 {'id': DateTime(2023, 8, 18), 'type': 'Type 1', 'value': 3}, {'id': DateTime(2023, 8, 18), 'type': 'Type 2', 'value': 3}, {'id': DateTime(2023, 8, 18), 'type': 'Type 3', 'value': 0}, ]; final types = { 'Type 1': const Color(0xfff39e58), 'Type 2': const Color(0xff707070), 'Type 3': const Color(0xffffc107) }; final listOfTicks = [ DateTime(2023, 8, 6), DateTime(2023, 8, 7), DateTime(2023, 8, 8), DateTime(2023, 8, 9), DateTime(2023, 8, 10), DateTime(2023, 8, 11), DateTime(2023, 8, 12), DateTime(2023, 8, 13), DateTime(2023, 8, 14), DateTime(2023, 8, 15), DateTime(2023, 8, 16), DateTime(2023, 8, 17), DateTime(2023, 8, 18), DateTime(2023, 8, 19), DateTime(2023, 8, 20), ]; return Chart( data: data, variables: { 'id': Variable( accessor: (Map<dynamic, dynamic> datum) => datum['id'] as DateTime, scale: TimeScale( formatter: (p0) => p0.day.toString(), max: listOfTicks.last, min: listOfTicks.first, ticks: listOfTicks, ), ), 'type': Variable( accessor: (Map map) => map['type'] as String, ), 'value': Variable( accessor: (Map map) => map['value'] as num, scale: LinearScale(min: 0, max: 10), ), }, marks: [ IntervalMark( position: Varset('id') * Varset('value') / Varset('type'), shape: ShapeEncode( value: RectShape( labelPosition: 0.5, ), ), color: ColorEncode( variable: 'type', values: types.values.toList(), ), label: LabelEncode( encoder: (tuple) => tuple['value'] == 0 ? Label('') : Label( tuple['value'].toString(), LabelStyle( textStyle: Theme.of(context) .textTheme .bodySmall! .copyWith(color: Colors.white), ), ), ), size: SizeEncode(value: 24), modifiers: [StackModifier()], ) ], coord: RectCoord(), axes: [ Defaults.horizontalAxis, Defaults.verticalAxis, ], selections: { 'tap': PointSelection( variable: 'id', ) }, tooltip: TooltipGuide(multiTuples: true), crosshair: CrosshairGuide(), ); } }
自动化补全工具函数(可选)
如果手动补数据繁琐,可以用以下函数自动生成完整数据:
List<Map<String, dynamic>> completeData(List<Map<String, dynamic>> rawData, List<String> allTypes, List<DateTime> allDates) { final result = <Map<String, dynamic>>[]; for (final date in allDates) { final dateData = rawData.where((d) => d['id'] == date).toList(); final existingTypes = dateData.map((d) => d['type'] as String).toSet(); for (final type in allTypes) { if (existingTypes.contains(type)) { result.add(dateData.firstWhere((d) => d['type'] == type)); } else { result.add({'id': date, 'type': type, 'value': 0}); } } } return result; }
内容的提问来源于stack exchange,提问作者Agus
相关产品推荐
相关产品推荐

