Fixed DateTime x axis from 12AM to 12AM (next day)

Hello!

I am using Cartesian chart to show real-time data graph on our app. The graph should have fixed y (0 to 400) and fixed x axis (time with format 12AM to 12AM of next day with interval 4 or 6 hours), and the data will be plotted by dashed line from database every 5 minutes). I've done most of the part but I couldn't find in documentation how to fix x axis so it would be great if you could help me with:

a) how to fix x axis with DateTime format and show labels (12AM, 6AM, 12PM, 6PM, 12AM). 

b) clear the graph line when it reaches 12AM of next day and restart updating every 5 minutes from beginning of graph to show results of next day. So I don't want users to scroll it or the graph to change x axis as its in real-time graph examples. It should just clear up and start drawing line on the same graph with fixed y and x axis.

Thank you! 





8 Replies

YG Yuvaraj Gajaraj Syncfusion Team June 22, 2022 05:40 PM UTC

Hi Natalia,


Greetings from Syncfusion. We have created the sample and attached it below, which will update the 24 hours of new data for the next day in each 5-second duration and show the axis label as you mentioned in the query by using the interval property and having a 6-hour interval (12 AM, 6 AM, 12 PM, 6 PM, 12 AM). You can modify the sample as per your requirement. We hope it will help you to achieve your requirement.


If you have any further queries, please get back to us.


Regards,

Yuvaraj.


Attachment: f175757_c893fcbd.zip


NA Natalia June 26, 2022 08:31 AM UTC

Thank you a lot for the sample! I have one a question regarding it, seems like the graph updates the whole chart (all data points) every 5 seconds, instead is it possible to edit it so that the list updates/adds new point every 5 seconds, so initial ChartData is only one data point at 12am, for ex: ("12am", 450). And after 5 seconds the list ChartData get updated with a new data point, so it becomes [("12am", 450), ("1am", 386)], and so on... When the list reaches 24 (next day 12AM), it clears the data from the list and puts the final point as a starting point for a new day. 

Second question is it possible to do remove the chart line and plot just data points with dots? or is it possible only with scatter chart?

Thanks a lot!



NA Natalia replied to Yuvaraj Gajaraj June 26, 2022 08:32 AM UTC

Thank you a lot for the sample! I have one a question regarding it, seems like the graph updates the whole chart (all data points) every 5 seconds, instead is it possible to edit it so that the list updates/adds new point every 5 seconds, so initial ChartData is only one data point at 12am, for ex: ("12am", 450). And after 5 seconds the list ChartData get updated with a new data point, so it becomes [("12am", 450), ("1am", 386)], and so on... When the list reaches 24 (next day 12AM), it clears the data from the list and puts the final point as a starting point for a new day. 

Second question is it possible to do remove the chart line and plot just data points with dots? or is it possible only with scatter chart?

Thanks a lot!



YG Yuvaraj Gajaraj Syncfusion Team June 27, 2022 02:17 PM UTC

Hi Natalia,


Please find the response for your queries below,


Query #1: graph updates the whole chart (all data points) every 5 seconds, instead is it possible to edit it so that the list updates/adds new point every 5 seconds, so initial ChartData is only one data point at 12am, for ex: ("12am", 450). And after 5 seconds the list ChartData get updated with a new data point, so it becomes [("12am", 450), ("1am", 386)], and so on... When the list reaches 24 (next day 12AM), it clears the data from the list and puts the final point as a starting point for a new day.


We have modified the sample, and it will start with one data point and add data for every 5 seconds, then remove the data points when the list reaches the next day, then have the last point as the first point. We have attached the sample below for your reference. We hope it will help you to achieve your requirement.


Query #2: Second question is it possible to do remove the chart line and plot just data points with dots? or is it possible only with scatter chart?


For this, you can enable the markerSettings in LineSeries and set the color value as transparent it will hide the line series and show the marker alone otherwise use the scatter series for your requirement. It will help you to achieve your requirements. We have attached the code snippet.


Code snippet:

LineSeries(

  color: Colors.transparent,

  markerSettings: MarkerSettings(

    isVisible: true,

  ),

  dataSource: chartData,

  xValueMapper: (ChartData data, _) => data.x,

  yValueMapper: (ChartData data, _) => data.y

),


Regards,

Yuvaraj.


Attachment: f175757_322e1c11.zip


NA Natalia June 30, 2022 03:23 PM UTC

Thanks for the assistance! The chart is good now, I've changed it according to my needs (show last 3 hours of data in viewport and live update), the final thing to fix is the chart does update and remove points accordingly for some time, but after a while it stops removing data points from chart, and I can't figure out why, because it does call updateDataSource(). And when I hot reload or refresh the emulator the chart goes normal again. I've attached my code, could you please check it?


class GlucoseLiveLineChart extends StatefulWidget {
/// Creates the realtime line chart sample.
const GlucoseLiveLineChart({Key? key}) : super(key: key);

@override
GlucoseLiveLineChartState createState() => GlucoseLiveLineChartState();
}

/// State class of the realtime line chart.
class GlucoseLiveLineChartState extends State<GlucoseLiveLineChart> {
GlucoseLiveLineChartState() {
timer = Timer.periodic(const Duration(seconds: 5), _updateDataSource);
}

Timer? timer;
List<ChartData>? chartData;
// late int count;
late int hours;
ChartSeriesController? _chartSeriesController;

@override
void dispose() {
timer?.cancel();
chartData!.clear();
_chartSeriesController = null;
super.dispose();
}

@override
void initState() {
// count = 1;
hours = 0;
chartData = <ChartData>[
ChartData(DateTime.now().subtract(Duration(hours: 3)), 0),
ChartData(DateTime.now().subtract(Duration(hours: 2)), 0),
ChartData(DateTime.now().subtract(Duration(hours: 1)), 0),
ChartData(DateTime.now(), Random().nextInt(110) + 10),
ChartData(
DateTime.now().add(Duration(minutes: 5)), Random().nextInt(400)),
];
super.initState();
}

@override
Widget build(BuildContext context) {
return Container(
child: _buildLiveLineChart(),
);
}

/// Returns the realtime Cartesian line chart.
SfCartesianChart _buildLiveLineChart() {
return SfCartesianChart(
plotAreaBorderWidth: 0,
margin: EdgeInsets.all(30),
tooltipBehavior: TooltipBehavior(enable: true),
primaryXAxis: DateTimeAxis(
interval: 60,
intervalType: DateTimeIntervalType.minutes,
dateFormat: DateFormat.jm(),
edgeLabelPlacement: EdgeLabelPlacement.shift,
majorGridLines: const MajorGridLines(width: 0),
labelStyle:
const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
primaryYAxis: NumericAxis(
interval: 100,
visibleMinimum: 0,
visibleMaximum: 400,
plotBands: [
PlotBand(
shouldRenderAboveSeries: false,
start: 70,
end: 180,
color: Colors.grey,
opacity: 0.3),
],
majorGridLines: MajorGridLines(width: 0.4, color: Colors.grey),
labelStyle:
const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
series: <LineSeries<ChartData, DateTime>>[
LineSeries<ChartData, DateTime>(
name: 'Glucose:',
color: Colors.transparent,
markerSettings: const MarkerSettings(
isVisible: true,
height: 1,
width: 1,
borderColor: Colors.white),
onRendererCreated: (ChartSeriesController controller) {
_chartSeriesController = controller;
},
dataSource: chartData!,

// dashArray: <double>[3, 5],
xValueMapper: (ChartData glucose, _) => glucose.time,
yValueMapper: (ChartData glucose, _) => glucose.glucoseLevel,
animationDuration: 0,
)
]);
}

// void _updateDataSource(Timer timer) {
// if (chartData!.last.country.difference(chartData!.first.country).inHours >=
// 3) {
// _chartSeriesController?.updateDataSource(
// removedDataIndexes: getIndexes(chartData!.length - 1));
// chartData!.removeRange(0, chartData!.length - 1);
// }
// chartData!.add(ChartData(
// DateTime(
// chartData!.last.country.year,
// chartData!.last.country.month,
// chartData!.last.country.day,
// chartData!.last.country.hour,
// chartData!.last.country.minute + 5),
// Random().nextInt(400)));
// _chartSeriesController?.updateDataSource(
// addedDataIndexes: [chartData!.length - 1],
// );
// }
void _updateDataSource(Timer timer) {
if (chartData!.length == 36 || chartData!.length > 36) {
chartData!.removeAt(0);
_chartSeriesController?.updateDataSource(
addedDataIndexes: <int>[chartData!.length - 1],
removedDataIndexes: <int>[0],
);
} else {
chartData!.add(ChartData(
DateTime(
//should change to current time while getting data from sensor
chartData!.last.time.year,
chartData!.last.time.month,
chartData!.last.time.day,
chartData!.last.time.hour,
chartData!.last.time.minute + 5),
Random().nextInt(180) + 10));
_chartSeriesController?.updateDataSource(
addedDataIndexes: <int>[chartData!.length - 1],
);
}
// count = count + 1;
}
}

/// Private class for storing the chart series data points.
class ChartData {
ChartData(this.time, this.glucoseLevel);
final DateTime time;
final num glucoseLevel;
}



NA Natalia replied to Yuvaraj Gajaraj June 30, 2022 03:25 PM UTC

Hi, Yuvaraj! Please check my reply above! Thanks!



NA Natalia replied to Yuvaraj Gajaraj July 1, 2022 08:16 AM UTC

So I've connected the chart to the API and everything is fine now, except the marker on the data point. It should show the y-axis and x-axis values right, but it shows incorrect x-axis value of DateTime (there is 10-15 minutes discrepancy between actual time in the Data Chart). Also it's changing, for ex on tap it shows 4:11AM, but then on second tap it shows 4:15AM. On the graph data plots correctly though. So if the data point is (5:10, 200), the point is in correct place, but when you tap on it the marker would show 4:56, 200. Data comes from API is milliseconds timestamp, which I convert to DateTime by millisecondsSinceEpoch method, which gives proper values, but on the graph the markers show some discrepancy and I am not sure why. This is important since our app claim to give the real time data every 5 minutes.



YG Yuvaraj Gajaraj Syncfusion Team July 3, 2022 05:52 AM UTC

Hi Natalia,


We have analyzed the code that is attached to your query, and we found that you have mentioned the added index inside the if condition in the _updateDataSource method. But in the `if` condition you only removed the data, so mentioned the added index is not necessary. So, please avoid that. Then you report lately that the tooltip value is not the same, and we check and ensured all are working fine with the same code snippet. If you still facing the issue, please try to provide a sample with the reproduce steps. It will be more helpful to us to provide a solution sooner.


Regards,

Yuvaraj.


Loader.
Up arrow icon