Articles in this section

How to use range selector and find difference between two dates in Cartesian charts?

Using the SfCartesianChart and SfRangeSelector can calculate the time difference between two points in the chart. The following steps explain how to find the time difference between the two selected data point is in the viewport of the chart.

 

Step 1: Declare the range controller of type RangeController, key of type GlobalKey globally, minimum, maximum and chart data for data source like in the following code snippet.

late RangeController rangeController;
GlobalKey<DisplayDifferenceState> key = GlobalKey<DisplayDifferenceState>();
final DateTime min = DateTime(2002, 01, 01, 10, 1, 1), max = DateTime(2002, 01, 01, 11, 1, 1);
late List<ChartSampleData> chartData;

 

Step 2: Initialize the data source and range controller in the initState method.

@override
void initState() {
 super.initState();
 chartData = <ChartSampleData>[
 ChartSampleData(
   x: DateTime(2002, 01, 01, 10, 1, 30), y: getRandomInt(10, 20)),
 ChartSampleData(
   x: DateTime(2002, 01, 01, 10, 2, 30), y: getRandomInt(10, 20)),
 ChartSampleData(
   x: DateTime(2002, 01, 01, 10, 3, 23), y: getRandomInt(10, 20)),
 ChartSampleData(
    x: DateTime(2002, 01, 01, 10, 4, 22), y: getRandomInt(10, 20)),
 ChartSampleData(
    x: DateTime(2002, 01, 01, 10, 5, 2), y: getRandomInt(20, 25)),
  ChartSampleData(
    x: DateTime(2002, 01, 01, 10, 6, 12), y: getRandomInt(10, 20)),
      …
     ];
    rangeController = RangeController(
      start: DateTime(2002, 01, 01, 10, 5, 10),
      end: DateTime(2002, 01, 01, 10, 35, 20),
    );
  }
 

 

Step 3: Create a stateful widget class (say DefaultRangeSelectorPage) and in the build method, configure the SfRangeSelector widget with required properties like in the below code snippet with child as SfCartesianChart widget.

class DefaultRangeSelectorPage extends StatefulWidget {
  @override
  _DefaultRangeSelectorPageState createState() =>
      _DefaultRangeSelectorPageState();
}
 
class _DefaultRangeSelectorPageState extends State<DefaultRangeSelectorPage> {
 
 @override
 Widget build(BuildContext context) {
   return Container( 
    child: SfRangeSelector(
      min: min,
      max: max,
      interval: 1,
      controller: rangeController,
      thumbShape: _CustomThumbShape(),
      onChanged: (SfRangeValues values) {
      if(key.currentState != null)
         key.currentState!.setState(() {});
       },
      child: SfCartesianChart(
                   primaryXAxis: DateTimeAxis(
                                  minimum: min,
                                  maximum: max,
                                  isVisible: true,
                                  labelIntersectAction:
                                      AxisLabelIntersectAction.hide,
                                  intervalType: DateTimeIntervalType.minutes,
                                  interval: 5,
                                  dateFormat: intl.DateFormat.Hms(),
                                  edgeLabelPlacement: EdgeLabelPlacement.shift,
                                  majorTickLines: MajorTickLines(width: 0)),
                   primaryYAxis: NumericAxis(
                                  isVisible: true,
                                  minimum: 8,
                                  maximum: 24,
                                  labelStyle: TextStyle(fontSize: 0),
                                  majorTickLines: MajorTickLines(width: 0)),
                   series:  <LineSeries<ChartSampleData, DateTime>>[
                                 LineSeries<ChartSampleData, DateTime>(
                                    dataSource: chartData,
                                    xValueMapper: (ChartSampleData sales, _) =>
                                        sales.x,
                                    yValueMapper: (ChartSampleData sales, _) =>
                                        sales.y,
                                    animationDuration: 0
                                 )
                   ],
                   //..
       )
     )
  );
}
 

 

In the above snippet, we refresh the state of text widget in the onChanged call-back which displays the time difference with respect to movement of range selector and can create custom thumb using the thumbShape property.

 

Step 4: Create Custom thumb shape class by extending the SfThumbShape class in which we have drawn two lines when perpendicular to the thumbs and you can change this as per your requirement.

 class _CustomThumbShape extends SfThumbShape {
  final Paint _paint = Paint()
    ..style = PaintingStyle.stroke
    ..color = Colors.blue
    ..strokeWidth = 2;
  @override
  void paint(PaintingContext context, Offset center,
      {required RenderBox parentBox,
      required RenderBox? child,
      required SfSliderThemeData themeData,
      SfRangeValues? currentValues,
      currentValue,
      required Paint? paint,
      required Animation<double> enableAnimation,
      required TextDirection textDirection,
      required SfThumb? thumb}) {
    context.canvas.drawLine(Offset(center.dx, center.dy - 30),
        Offset(center.dx, chartHeight + 130.toDouble()), _paint);
  }
}
 

 

Step 5:  Create a custom text widget to calculate and display the time difference by using the range controller values obtained from configured range selector widget.

class DisplayDifference extends StatefulWidget {
 
DisplayDifference({Key? key}) : super (key: key);
 
  @override
  DisplayDifferenceState createState() => DisplayDifferenceState();
}
 
class DisplayDifferenceState extends State<DisplayDifference> {
  int _getDifferenceBetweenDate(RangeController values) {
   // From the range controller values calculates the difference between them.
    DateTime start, end;
    int difference;
    start = values.start;
    end = values.end;
    difference = end.difference(start).inMinutes;
 
    return difference;
  }
 
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 20,
      child: Text(
        'Difference   :   ' +
            _getDifferenceBetweenDate(rangeController).toString() + ' '
            'Minutes',
        style: const TextStyle(fontSize: 16),
      ),
    );
  }
}
 

 

Step 6: Create a main class (say DifferenceCallipers) extending the Stateful widget class and in the build method, wrap the configured range selector widget class (DefaultRangeSelectorPage) and custom text widget class (DisplayDifference) line in the below code snippet.

class DifferenceCallipers extends StatefulWidget {

  @override

  DifferenceCallipersState createState() => DifferenceCallipersState();

}

 

class DifferenceCallipersState extends State<DifferenceCallipers> {

  @override

  Widget build(BuildContext context) {

    return Scaffold(

        appBar: AppBar(),

        body: Column(

          mainAxisAlignment: MainAxisAlignment.center,

          children: [DefaultRangeSelectorPage(), DisplayDifference(key: key)],

        ));

  }

}

 

Thus, the time difference can be calculated between the selected data points in the chart using the SfCartesianchart and SfRangeSelector widget.

 

time_difference

 

View the Github Sample here.

Conclusion

I hope you enjoyed learning about how to use range selector and find difference between two dates in Cartesian charts.

You can refer to our  Flutter CartesianChart feature tour page to learn about its other groundbreaking feature representations. You can also explore our Flutter CartesianChart documentation to understand how to create and manipulate data.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion®, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forumsDirect-Trac, or feedback portal. We are always happy to assist you!

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Access denied
Access denied