Files
fl_chart/example/lib/presentation/samples/line/line_chart_sample6.dart
zypherift c7e3f36b06
Some checks failed
Code Coverage / upload (push) Has been cancelled
Gh-Pages / build (push) Has been cancelled
Code Verification / verify (push) Has been cancelled
1.0.0
2025-08-09 18:17:34 +02:00

287 lines
8.4 KiB
Dart

import 'package:fl_chart_app/presentation/resources/app_resources.dart';
import 'package:fl_chart_app/util/extensions/color_extensions.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class LineChartSample6 extends StatelessWidget {
LineChartSample6({
super.key,
Color? line1Color1,
Color? line1Color2,
Color? line2Color1,
Color? line2Color2,
}) : line1Color1 = line1Color1 ?? AppColors.contentColorOrange,
line1Color2 = line1Color2 ?? AppColors.contentColorOrange.darken(60),
line2Color1 = line2Color1 ?? AppColors.contentColorBlue.darken(60),
line2Color2 = line2Color2 ?? AppColors.contentColorBlue {
minSpotX = spots.first.x;
maxSpotX = spots.first.x;
minSpotY = spots.first.y;
maxSpotY = spots.first.y;
for (final spot in spots) {
if (spot.x > maxSpotX) {
maxSpotX = spot.x;
}
if (spot.x < minSpotX) {
minSpotX = spot.x;
}
if (spot.y > maxSpotY) {
maxSpotY = spot.y;
}
if (spot.y < minSpotY) {
minSpotY = spot.y;
}
}
}
final Color line1Color1;
final Color line1Color2;
final Color line2Color1;
final Color line2Color2;
final spots = const [
FlSpot(0, 1),
FlSpot(2, 5),
FlSpot(4, 3),
FlSpot(6, 5),
];
final spots2 = const [
FlSpot(0, 3),
FlSpot(2, 1),
FlSpot(4, 2),
FlSpot(6, 1),
];
late double minSpotX;
late double maxSpotX;
late double minSpotY;
late double maxSpotY;
Widget leftTitleWidgets(double value, TitleMeta meta) {
final style = TextStyle(
color: line1Color1,
fontWeight: FontWeight.bold,
fontSize: 18,
);
final intValue = reverseY(value, minSpotY, maxSpotY).toInt();
if (intValue == (maxSpotY + minSpotY)) {
return Text('', style: style);
}
return Padding(
padding: const EdgeInsets.only(right: 6),
child: Text(
intValue.toString(),
style: style,
textAlign: TextAlign.center,
),
);
}
Widget rightTitleWidgets(double value, TitleMeta meta) {
final style = TextStyle(
color: line2Color2,
fontWeight: FontWeight.bold,
fontSize: 18,
);
final intValue = reverseY(value, minSpotY, maxSpotY).toInt();
if (intValue == (maxSpotY + minSpotY)) {
return Text('', style: style);
}
return Text(intValue.toString(), style: style, textAlign: TextAlign.right);
}
Widget topTitleWidgets(double value, TitleMeta meta) {
if (value % 1 != 0) {
return Container();
}
const style = TextStyle(
fontWeight: FontWeight.bold,
color: AppColors.mainTextColor2,
);
return SideTitleWidget(
meta: meta,
child: Text(value.toInt().toString(), style: style),
);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(right: 22, bottom: 20),
child: AspectRatio(
aspectRatio: 2,
child: LineChart(
LineChartData(
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
tooltipBorderRadius: BorderRadius.zero,
getTooltipColor: (spot) => Colors.white,
getTooltipItems: (List<LineBarSpot> touchedSpots) {
return touchedSpots.map((LineBarSpot touchedSpot) {
return LineTooltipItem(
touchedSpot.y.toString(),
TextStyle(
color: touchedSpot.bar.gradient!.colors.first,
fontWeight: FontWeight.bold,
fontSize: 20,
),
);
}).toList();
},
),
getTouchedSpotIndicator: (
_,
indicators,
) {
return indicators
.map((int index) => const TouchedSpotIndicatorData(
FlLine(color: Colors.transparent),
FlDotData(show: false),
))
.toList();
},
touchSpotThreshold: 12,
distanceCalculator:
(Offset touchPoint, Offset spotPixelCoordinates) =>
(touchPoint - spotPixelCoordinates).distance,
),
lineBarsData: [
LineChartBarData(
gradient: LinearGradient(
colors: [
line1Color1,
line1Color2,
],
),
spots: reverseSpots(spots, minSpotY, maxSpotY),
isCurved: true,
isStrokeCapRound: true,
barWidth: 10,
belowBarData: BarAreaData(
show: false,
),
dotData: FlDotData(
show: true,
getDotPainter: (spot, percent, barData, index) {
return FlDotCirclePainter(
radius: 12,
color: Color.lerp(
line1Color1,
line1Color2,
percent / 100,
)!,
strokeColor: Colors.white,
strokeWidth: 1,
);
},
),
),
LineChartBarData(
gradient: LinearGradient(
colors: [
line2Color1,
line2Color2,
],
),
spots: reverseSpots(spots2, minSpotY, maxSpotY),
isCurved: true,
isStrokeCapRound: true,
barWidth: 10,
belowBarData: BarAreaData(
show: false,
),
dotData: FlDotData(
show: true,
getDotPainter: (spot, percent, barData, index) {
return FlDotCirclePainter(
radius: 12,
color: Color.lerp(
line2Color1,
line2Color2,
percent / 100,
)!,
strokeColor: Colors.white,
strokeWidth: 1,
);
},
),
),
],
minY: 0,
maxY: maxSpotY + minSpotY,
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: leftTitleWidgets,
reservedSize: 38,
),
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: rightTitleWidgets,
reservedSize: 30,
),
),
bottomTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 32,
getTitlesWidget: topTitleWidgets,
),
),
),
gridData: FlGridData(
show: true,
drawVerticalLine: true,
checkToShowHorizontalLine: (value) {
final intValue = reverseY(value, minSpotY, maxSpotY).toInt();
if (intValue == (maxSpotY + minSpotY).toInt()) {
return false;
}
return true;
},
),
borderData: FlBorderData(
show: true,
border: const Border(
left: BorderSide(color: AppColors.borderColor),
top: BorderSide(color: AppColors.borderColor),
bottom: BorderSide(color: Colors.transparent),
right: BorderSide(color: Colors.transparent),
),
),
),
),
),
);
}
double reverseY(double y, double minX, double maxX) {
return (maxX + minX) - y;
}
List<FlSpot> reverseSpots(List<FlSpot> inputSpots, double minY, double maxY) {
return inputSpots.map((spot) {
return spot.copyWith(y: (maxY + minY) - spot.y);
}).toList();
}
}