Dear team,
My app displays revenues and expenses in a chart as two seperate ColumnSeries. The x-axis is in DateTime format.
For a more detailed view the user can choose a range which I set by minimum and maximum parameters for the x-axis. If I do so, the zoom for y-axis stays zoomed on the lowest and highest data points of the whole data set. Therefore, it is possible the the shown data subset is not filling the graph. To overcome this, I calculate the y-axis zoom manually. This part works good.
If the user is now disabling one series by tapping on the legend item for this series the data for this is not visible any more as it is intended.
I'd like to recalculate the zoom of the y-axis after the user has tapped on the legend item. For instance, if the expenses are hidden the negative part of the y-axis do not need to be visible. Unfortunately, I didn't found a way to do this.
I tried the onLegendTapped callback but the isVisible status of the series is set to null. Therefore I cannot toggle it.
Do you have any idea?
Best,
S
Hi Stephan,
We have validated your query and would like to inform you that the axis range is updated based on the visible series data points by default. Upon reviewing your screenshot, we suspect that you have set the y-axis minimum value to -163 and the maximum value to 387, which is why the axis range is not updated based on visible series data points.
To resolve this issue, you can remove the y-axis minimum, maximum, visible minimum, and visible maximum values in your application.
primaryYAxis: NumericAxis( |
Regards,
Lavanya A.
Hi Lavanya,
Thanks for your quick answer!
Yes, I have set minimum and maximum for y-axis. If I don't set them I will get a graph auto zooming as you said. But: it is showing lots of white, because the zoom is set for the lowest and highest data value - which is fine if all data is shown. Since I show only a range of data with by setting minimum and maximum for x-axis, the shown part of the data might be quite smaller than the global data max and min.
Since I didn't find a solution for "auto zoom" with set min and max for x-axis I am calculating the min and max of the shown data to set the range for y-axis.
That is why I am looking for a solution to get notified if the user changed the visibility of a data series.
Best,
Hi Stephan,
Currently, we are checking the feasible workaround for your requirement and will update the complete details on February 14, 2023. We appreciate your patience until then.
Regards,
Yuvaraj.
Hi Stephan,
We suggest you use the anchorRangeToVisiblePoints property in the primaryYAxis, it will help you to have a y-axis range based on the visible data points only. We have shared the code snippet below for your reference.
Code snippet:
primaryYAxis: NumericAxis( anchorRangeToVisiblePoints: true ) |
UG, https://help.syncfusion.com/flutter/cartesian-charts/axis-customization#auto-range-calculation
Regards,
Yuvaraj.
Hi,
Unfortunately this does not solve the problem. I created an example for demonstration of the issue:
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool ranged = false;
bool calculatedZoom = false;
DateTime? _startDate;
DateTime? _endDate;
@override
Widget build(BuildContext context) {
final List<ChartData> inData = [
ChartData(DateTime(2023, 1), 1000),
ChartData(DateTime(2023, 2), 100),
];
final List<ChartData> outData = [
ChartData(DateTime(2023, 1), -500),
ChartData(DateTime(2023, 2), -50),
];
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Column(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
children: [
Row(
children: [
const Text("Ranged"),
Switch(
// This bool value toggles the switch.
value: ranged,
activeColor: Colors.red,
onChanged: (bool value) {
// This is called when the user toggles the switch.
setState(() {
ranged = value;
_setDataRange();
});
}),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SfCartesianChart(
enableSideBySideSeriesPlacement: false,
primaryYAxis: NumericAxis(
// minimum: min,
// maximum: max,
),
primaryXAxis: DateTimeAxis(
minimum: _startDate, maximum: _endDate),
legend: Legend(
isVisible: true, position: LegendPosition.top),
series: <ChartSeries<ChartData, DateTime>>[
ColumnSeries<ChartData, DateTime>(
dataSource: inData,
xValueMapper: (ChartData data, _) => data.x,
yValueMapper: (ChartData data, _) => data.y,
emptyPointSettings:
EmptyPointSettings(mode: EmptyPointMode.zero),
name: "in",
color: Colors.green,
opacity: 0.75,
),
ColumnSeries<ChartData, DateTime>(
dataSource: outData,
xValueMapper: (ChartData data, _) => data.x,
yValueMapper: (ChartData data, _) => data.y,
name: "out",
color: Colors.red,
opacity: 0.75,
emptyPointSettings:
EmptyPointSettings(mode: EmptyPointMode.zero),
),
])))
]),
);
}
_setDataRange() {
setState(() {
if (ranged) {
_startDate = DateTime(2023, 2);
_endDate = DateTime(2023, 3);
} else {
// fall back
_startDate = null;
_endDate = null;
}
});
}
}
class ChartData {
ChartData(this.x, this.y);
final DateTime x;
final double y;
}
Showing all data zooms fine. If you select the ranged data only the last part of data is shown but the zoom does not adapt. This results in unfavorable data view. If the data spread is even bigger the user might not see any data at all after selecting a range of data.
Can you provide a hint of to zoom the data when only a range of data is displayed? This should also work if the user is de-selecting on data series by tapping on the legend item.
Hi Stephan,
Currently, we are checking the feasible workaround for your requirement and will update the complete details on February 20, 2023. We appreciate your patience until then.
Regards,
Yuvaraj.
Hi Stephan,
We have reviewed your code snippet and found that you modified the minimum and maximum properties of the primaryXAxis, as a result, the visible range of the y-axis did not change. To update the visible range of the chart, we recommend using the visibleMinimum and visibleMaximum properties of the axis instead of the minimum and maximum properties. For your reference, we have included a code snippet and sample below.
Code snippet:
primaryXAxis: DateTimeAxis( visibleMinimum: _startDate, visibleMaximum: _endDate, ), |
Regards,
Yuvaraj.