We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Zoom after disabling series view via tapping on legend item

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.

Screenshot_20230210-101412.png

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.

Screenshot_20230210-115037.jpg

Do you have any idea?

Best,

S


7 Replies

LA Lavanya Anaimuthu Syncfusion Team February 10, 2023 02:19 PM UTC

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(minimum: -163, maximum: 387),


Regards,

Lavanya A.



ST Stephan replied to Lavanya Anaimuthu February 10, 2023 04:00 PM UTC

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.


Screenshot_20230210_165129.png


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,



YG Yuvaraj Gajaraj Syncfusion Team February 13, 2023 03:08 PM UTC

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.



YG Yuvaraj Gajaraj Syncfusion Team February 14, 2023 02:53 PM UTC

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.



ST Stephan February 16, 2023 05:10 PM UTC

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.



YG Yuvaraj Gajaraj Syncfusion Team February 17, 2023 03:56 PM UTC

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.



YG Yuvaraj Gajaraj Syncfusion Team February 20, 2023 12:31 PM UTC

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.


Attachment: f180455_6515cc37.zip

Loader.
Up arrow icon