Skip to content

Commit

Permalink
Add error text in the FlSimpleErrorPainter
Browse files Browse the repository at this point in the history
  • Loading branch information
imaNNeo committed Jan 10, 2025
1 parent fcda4ee commit 7ccc1ca
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 33 deletions.
67 changes: 34 additions & 33 deletions example/lib/presentation/samples/line/line_chart_sample13.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:fl_chart_app/util/csv_parser.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


class LineChartSample13 extends StatefulWidget {
const LineChartSample13({super.key});

Expand Down Expand Up @@ -48,14 +47,14 @@ class _LineChartSample13State extends State<LineChartSample13> {

void _loadWeatherData() async {
final data =
await rootBundle.loadString('assets/data/amsterdam_2024_weather.csv');
await rootBundle.loadString('assets/data/amsterdam_2024_weather.csv');
final rows = CsvParser.parse(data);
if (!mounted) {
return;
}
setState(() {
final allWeatherData =
rows.skip(1).map((row) => _WeatherData.fromCsv(row)).toList();
rows.skip(1).map((row) => _WeatherData.fromCsv(row)).toList();
monthlyWeatherData = List.generate(12, (index) {
final month = index + 1;
return allWeatherData
Expand Down Expand Up @@ -89,15 +88,17 @@ class _LineChartSample13State extends State<LineChartSample13> {
),
Tooltip(
message: 'Source: visualcrossing.com',
child: IconButton(onPressed: () {
AppUtils().tryToLaunchUrl(
'https://www.visualcrossing.com/weather-history/Amsterdam,Netherlands/metric/2024-01-01/2024-12-31',
);
}, icon: const Icon(
Icons.info_outline_rounded,
color: AppColors.contentColorOrange,
size: 18,
)),
child: IconButton(
onPressed: () {
AppUtils().tryToLaunchUrl(
'https://www.visualcrossing.com/weather-history/Amsterdam,Netherlands/metric/2024-01-01/2024-12-31',
);
},
icon: const Icon(
Icons.info_outline_rounded,
color: AppColors.contentColorOrange,
size: 18,
)),
)
],
),
Expand Down Expand Up @@ -199,19 +200,18 @@ class _LineChartSample13State extends State<LineChartSample13> {
leftTitles: AxisTitles(
drawBelowEverything: true,
sideTitles: SideTitles(
showTitles: true,
maxIncluded: false,
minIncluded: false,
reservedSize: 40,
getTitlesWidget: (double value, TitleMeta meta) {
return SideTitleWidget(
meta: meta,
child: Text(
'${meta.formattedValue}°',
),
);
}
),
showTitles: true,
maxIncluded: false,
minIncluded: false,
reservedSize: 40,
getTitlesWidget: (double value, TitleMeta meta) {
return SideTitleWidget(
meta: meta,
child: Text(
'${meta.formattedValue}°',
),
);
}),
),
bottomTitles: AxisTitles(
axisNameWidget: Container(
Expand Down Expand Up @@ -277,13 +277,16 @@ class _LineChartSample13State extends State<LineChartSample13> {
});
}

FlSpotErrorRangePainter _errorPainter(FlSpot spot,
LineChartBarData bar,
int spotIndex,) =>
FlSpotErrorRangePainter _errorPainter(
FlSpot spot,
LineChartBarData bar,
int spotIndex,
) =>
FlSimpleErrorPainter(
lineWidth: 1.0,
lineColor:
_interactedSpotIndex == spotIndex ? Colors.white : Colors.white38,
_interactedSpotIndex == spotIndex ? Colors.white : Colors.white38,
showErrorTexts: _interactedSpotIndex == spotIndex,
);

FlLine _horizontalGridLines(double value) {
Expand Down Expand Up @@ -416,8 +419,7 @@ class _WeatherData with EquatableMixin {
// parse from csv row
// name,datetime,tempmax,tempmin,temp,feelslikemax,feelslikemin,feelslike,dew,humidity,precip,precipprob,precipcover,preciptype,snow,snowdepth,windgust,windspeed,winddir,sealevelpressure,cloudcover,visibility,solarradiation,solarenergy,uvindex,severerisk,sunrise,sunset,moonphase,conditions,description,icon,stations
// "Amsterdam,Netherlands",2024-01-01,9.1,6.4,8,5.3,2.5,4.1,5.1,82.4,14.26,100,37.5,rain,0,0,53.9,40.2,225.9,1000.1,88.7,20.5,20.6,1.8,2,,2024-01-01T08:50:34,2024-01-01T16:37:06,0.68,"Rain, Partially cloudy",Partly cloudy throughout the day with a chance of rain throughout the day.,rain,"06260099999,D3248,06348099999,06249099999,C0449,06240099999,06269099999,06257099999,06344099999"
factory _WeatherData.fromCsv(List<String> row) =>
_WeatherData(
factory _WeatherData.fromCsv(List<String> row) => _WeatherData(
name: row[0],
datetime: DateTime.parse(row[1]),
tempmax: double.parse(row[2]),
Expand Down Expand Up @@ -454,8 +456,7 @@ class _WeatherData with EquatableMixin {
);

@override
List<Object?> get props =>
[
List<Object?> get props => [
name,
datetime,
tempmax,
Expand Down
95 changes: 95 additions & 0 deletions lib/src/chart/base/axis_chart/axis_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,12 @@ class FlSimpleErrorPainter extends FlSpotErrorRangePainter with EquatableMixin {
this.lineWidth = 1.0,
this.capLength = 8.0,
this.crossAlignment = 0,
this.showErrorTexts = false,
this.errorTextStyle = const TextStyle(
color: Colors.white,
fontSize: 12,
),
this.errorTextDirection = TextDirection.ltr,
}) {
_linePaint = Paint()
..color = lineColor
Expand All @@ -1755,6 +1761,9 @@ class FlSimpleErrorPainter extends FlSpotErrorRangePainter with EquatableMixin {
final double lineWidth;
final double capLength;
final double crossAlignment;
final bool showErrorTexts;
final TextStyle errorTextStyle;
final TextDirection errorTextDirection;

late final Paint _linePaint;

Expand All @@ -1773,6 +1782,28 @@ class FlSimpleErrorPainter extends FlSpotErrorRangePainter with EquatableMixin {
Offset(offsetInCanvas.dx, rect.top),
Offset(offsetInCanvas.dx, rect.bottom),
);

if (showErrorTexts) {
// lower
_drawErrorText(
canvas: canvas,
rect: rect,
isHorizontal: false,
isLower: true,
text: (origin.y - origin.yError!.lowerBy).toString(),
textStyle: errorTextStyle,
);

// upper
_drawErrorText(
canvas: canvas,
rect: rect,
isHorizontal: false,
isLower: false,
text: (origin.y + origin.yError!.upperBy).toString(),
textStyle: errorTextStyle,
);
}
}

final hasHorizontalError = errorRelativeRect.width != 0;
Expand All @@ -1782,6 +1813,28 @@ class FlSimpleErrorPainter extends FlSpotErrorRangePainter with EquatableMixin {
Offset(rect.left, offsetInCanvas.dy),
Offset(rect.right, offsetInCanvas.dy),
);

if (showErrorTexts) {
// lower
_drawErrorText(
canvas: canvas,
rect: rect,
isHorizontal: true,
isLower: true,
text: (origin.x - origin.xError!.lowerBy).toString(),
textStyle: errorTextStyle,
);

// upper
_drawErrorText(
canvas: canvas,
rect: rect,
isHorizontal: true,
isLower: false,
text: (origin.x + origin.xError!.upperBy).toString(),
textStyle: errorTextStyle,
);
}
}
}

Expand Down Expand Up @@ -1838,10 +1891,52 @@ class FlSimpleErrorPainter extends FlSpotErrorRangePainter with EquatableMixin {
}
}

void _drawErrorText({
required Canvas canvas,
required Rect rect,
required bool isHorizontal,
required bool isLower,
required String text,
required TextStyle textStyle,
}) {
final lowerText = TextPainter(
text: TextSpan(
text: text,
style: textStyle,
),
textDirection: TextDirection.ltr,
)..layout();

const spacing = 4.0;
final textX = isHorizontal
? isLower
? rect.left - lowerText.width - spacing
: rect.right + spacing
: rect.center.dx - lowerText.width / 2;

final textY = isHorizontal
? rect.center.dy - lowerText.height / 2
: isLower
? rect.bottom + spacing
: rect.top - lowerText.width - spacing;

lowerText.paint(
canvas,
Offset(
textX,
textY,
),
);
}

@override
List<Object?> get props => [
lineColor,
lineWidth,
capLength,
crossAlignment,
showErrorTexts,
errorTextStyle,
errorTextDirection,
];
}

0 comments on commit 7ccc1ca

Please sign in to comment.