fl_chart
fl_chart copied to clipboard
Line Chart SideTitles follow interval incorrectly
The Max value of the axis titles does not follow the given interval by default which renders the built-in interval calculation useless in some cases.
For example with values [3.14, 5, 6.2, 8.2, 12, 12.2]
on the Y axis
and interval = 1
or default interval
the middle titles will follow this interval but the baseline
will be 3.14
and maxY
value will be 12.2
. I think it should be 3
and 13
. I know as a workaround I could set the baseline
and maxY
value myself but if I'm using the default interval that is calculated under the hood there might be no way to know what should be the correct maxY
value. Maybe there is currently a way to change this behavior that I don't know of?
I'm pretty sure this is due to the changes done to interval recently as I'm only facing this issue after upgrading FlChart from 0.40.6
Sample LineChart widget
Chart();
@override
State<Chart> createState() => _ChartState();
}
class _ChartState extends State<Chart> {
@override
Widget build(BuildContext context) {
return LineChart(
LineChartData(
borderData: FlBorderData(
border: Border.all(
color: Colors.white12,
width: 1.0,
style: BorderStyle.solid,
),
),
titlesData: FlTitlesData(
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 60,
getTitlesWidget: (value, meta) {
return Container(
margin: const EdgeInsets.only(left: 10),
child: Text(value.toString()),
);
}),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
interval: 2,
getTitlesWidget: (value, meta) {
return Text(value.toString());
},
)),
),
gridData: FlGridData(),
lineBarsData: [
LineChartBarData(
barWidth: 2.5,
isCurved: false,
dotData: FlDotData(show: false),
color: Colors.green,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xff19a629).withOpacity(0.5),
const Color(0xff19a629).withOpacity(0.05),
],
),
),
spots: [
FlSpot(1.0, 3.14),
FlSpot(2.0, 5.28),
FlSpot(3.0, 9.22),
FlSpot(4.0, 12.3),
FlSpot(5.0, 3.14),
],
)
],
),
);
}
}
Screenshots
Versions
- Flutter: 2.10.3
- FlChart: 0.50.1
Is this related? https://github.com/imaNNeoFighT/fl_chart/issues/906
It is related, however, no solution was provided. As a workaround, I could hide the min and max titles but the axis would look weird in my opinion. Would be nice if there was some way to get the titles to follow the interval completely (display nearest number in interval instead of min and max values).
It is related, however, no solution was provided. As a workaround, I could hide the min and max titles but the axis would look weird in my opinion. Would be nice if there was some way to get the titles to follow the interval completely (display nearest number in interval instead of min and max values).
Here is a comment I posted in #906 that addresses this issue. Hiding the min and max titles would result to an undesired behavior because it could be that the max value aligns with the interval and therefore should be rendered. However, if you are hiding it then it will not be rendered.
Hi, guys. It's my first post, so please be patient. I have the same question.
I have some array of DateTime: FlSpot(1640988000000, 1), //2022/01/01 00:00 FlSpot(1640991600000, 2), //2022/01/01 01:00 FlSpot(1640995200000, 1), //2022/01/01 02:00 FlSpot(1640998800000, 2), //2022/01/01 03:00 FlSpot(1641002400000, 1), //2022/01/01 04:00 FlSpot(1641006000000, 2), //2022/01/01 05:00
And Interval: 3000000; // 50 minutes
Expected values and fact values is correct.
Expected values: 1640988000000.0 : 00:00 1640991000000.0 : 00:50 1640994000000.0 : 01:40 1640997000000.0 : 02:30 1641000000000.0 : 03:20 1641003000000.0 : 04:10 1641006000000.0 : 05:00
Fact values: [log] 1640988000000.0 : 00:00 [log] 1640991000000.0 : 00:50 [log] 1640994000000.0 : 01:40 [log] 1640997000000.0 : 02:30 [log] 1641000000000.0 : 03:20 [log] 1641003000000.0 : 04:10 [log] 1641006000000.0 : 05:00
But when array of DateTime is: FlSpot(1640995200000, 1), //2022/01/01 02:00 FlSpot(1640998800000, 2), //2022/01/01 03:00 FlSpot(1641002400000, 1), //2022/01/01 04:00 FlSpot(1641006000000, 2), //2022/01/01 05:00 FlSpot(1641009600000, 1), //2022/01/01 06:00 FlSpot(1641013200000, 2), //2022/01/01 07:00
And the same interval: 3000000; // 50 minutes
Expected values and fact values is not identical.
Expected values: 1640995200000.0 : 02:00 1640998200000.0 : 02:50 1641001200000.0 : 03:40 1641004200000.0 : 04:30 1641007200000.0 : 05:20 1641010200000.0 : 06:10 1641013200000.0 : 07:00
Fact values: [log] 1640995200000.0 : 02:00 [log] 1640997000000.0 : 02:30 <-- 30 minutes difference [log] 1641000000000.0 : 03:20 [log] 1641003000000.0 : 04:10 [log] 1641006000000.0 : 05:00 [log] 1641009000000.0 : 05:50 [log] 1641012000000.0 : 06:40 [log] 1641013200000.0 : 07:00 <-- 20 minutes difference
Could you please explain why value have incorrect interval?
Thank you so much.
Versions:
- Flutter version 2.10.4
- Dart version 2.16.2
- fl_chart: 0.50.6
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:fl_chart/fl_chart.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FL Chart Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(
height: 300,
child: Padding(
padding: const EdgeInsets.all(24),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: const [
// FlSpot(1640988000000, 1), //2022/01/01 00:00
// FlSpot(1640991600000, 2), //2022/01/01 01:00
FlSpot(1640995200000, 1), //2022/01/01 02:00
FlSpot(1640998800000, 2), //2022/01/01 03:00
FlSpot(1641002400000, 1), //2022/01/01 04:00
FlSpot(1641006000000, 2), //2022/01/01 05:00
FlSpot(1641009600000, 1), //2022/01/01 06:00
FlSpot(1641013200000, 2), //2022/01/01 07:00
],
),
],
gridData: FlGridData(
show: false,
),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
topTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
interval: 3000000, // 50 minutes
getTitlesWidget: (double value, TitleMeta meta) {
String dateTimeString = DateFormat('HH:mm').format(DateTime.fromMillisecondsSinceEpoch(value.toInt()));
log('$value : $dateTimeString');
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(dateTimeString),
);
},
),
),
),
),
),
),
),
],
),
);
}
}
Can you please confirm that this issue still exists or not?
I remember we solved this issue a while ago.
I believe it is still not solved yet. The auto-defined maxY is still the highest value in the dataset instead of the next auto-defined interval just like the example from @MatasRut. More examples are below:
The appropriate maxY would be just the next interval 25%. The max value here is 20.6.
The next interval should be 250 instead of the max value 218.
I'm using the latest version 0.61.0.
I believe it is still not solved yet. The auto-defined maxY is still the highest value in the dataset instead of the next auto-defined interval just like the example from @MatasRut. More examples are below:
What if you disable showing the max value?
BTW we have a duplicate issue here: #906. Please follow it. I am going to close this issue