How to set different border radius for each Rect series data points by extending the implementation of Cartesian charts (SfCartesianChart) ?
In this article, we described how to set different border radius for each chart Rect series data points using extendibility (inheritance) in Cartesian chart.
Flutter Cartesian Chart widget provides support for extending the chart series, with which you can use the override methods and properties of the chart series for customization purposes. Extendibility or inheritance is defined as the process of deriving the properties and characteristics of another class. It provides the ability to create a new class from an existing class so that you can use the properties and characteristics of the existing class. By using the onCreateRenderer property available in the chart, you can create a custom chart series renderer using extendibility and return that series renderer to this property so that the application-level series rendering customization will get reflected in the chart.
Refer the following instructions, to set different border radius for each series data points using extendibility.
Step 1: First, create a new class CustomColumnSeriesRenderer extending ColumnSeriesRenderer class.
// Custom column series renderer created class CustomColumnSeriesRenderer<T, D> extends ColumnSeriesRenderer<T, D> { CustomColumnSeriesRenderer(); }
Step 2: Create another custom painter class CustomColumnSeriesPainter extending ColumnSegment class and then override the createSegment() method in the previously created CustomColumnSeriesRenderer class and return the CustomColumnSeriesPainter class inside that method.
class CustomColumnSeriesRenderer<T, D> extends ColumnSeriesRenderer<T, D> { CustomColumnSeriesRenderer(); @override ColumnSegment<T, D> createSegment() { // Custom segment painter returned return CustomChartPainter(); } } // Initialized custom cegment painter for customizing each segments of the chart series class CustomColumnSeriesPainter<T, D> extends ColumnSegment<T, D> { }
Step 3: Inside the CustomColumnSeriesPainter class, create temporary Rect variable for storing the values of the segmentRect property of the ColumnSegment class. This property holds the rect values of each column segment that is to be painted in the chart.
class CustomColumSeriesPainter<T, D> extends ColumnSegment<T, D> { late Rect rect; }
After that, override the onPaint() method of the ColumnSegment, in which each column segment properties can be customized. Here, we have modified two different border radii for the column segments based on their y values. For setting the border radii for each segment inside the onPaint() method, you can use the RRect.fromRectAndCorners() method to specify radius for the each segment rect’s corners and assign the result RRect value to the segmentRect property itself.
Here, we have used the currentSegmentIndex property’s value to parse using the chart data source for setting the border radius.
class CustomColumnSeriesPainter<T, D> extends ColumnSegment<T, D> { // Initialized a temporary rect to store the segment rect of each column late Rect rect; @override void onPaint(Canvas canvas) { // Stored the segment rect in the temporary rect variable rect = segmentRect!.outerRect; // Here, if the value is above 35, the bottom corner parts of the column segment will be rounded. if (chartData[currentSegmentIndex].sales > 35) { // Modified the radius of the segment rect corners using RRect.fromRectAndCorners method. segmentRect = RRect.fromRectAndCorners(rect, bottomLeft: Radius.circular(25), bottomRight: Radius.circular(25)); // Here, if the value is below 35, the top corner parts of the column segment will be rounded. } else if (chartData[currentSegmentIndex].sales < 35) { segmentRect = RRect.fromRectAndCorners(rect, topLeft: Radius.circular(25), topRight: Radius.circular(25)); } // You can set the radius values as per your wish using the necessary parameters (such as topLeft, // topRight, bottomRight, bottomLeft) of the RRect.fromRectAndCorners method. // Called the superclass method and properties for column segment rendering. super.onPaint(canvas); } }
Step 4: Initialize the chart data source globally and then initialize the SfCartesianChart with all the required properties and finally return the CustomColumSeriesRenderer class to the onCreateRenderer property of the chart series.
// Initialize the chart's data source globally. List<_SalesData> chartData = <_SalesData>[ _SalesData('Jan', 36), _SalesData('Feb', 28), _SalesData('Mar', 34), _SalesData('Apr', 32), _SalesData('May', 40) ]; // State class that holds the chart widget class _MyHomePageState extends State<_MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( body: SfCartesianChart( primaryXAxis: CategoryAxis(), series: <ColumnSeries<_SalesData, String>>[ ColumnSeries<_SalesData, String>( // Property with which the overriding is done in the chart. onCreateRenderer: (ChartSeries<dynamic, dynamic> series) { // returned the custom series renderer return CustomColumnSeriesRenderer(); }, dataSource: chartData, xValueMapper: (_SalesData sales, _) => sales.year, yValueMapper: (_SalesData sales, _) => sales.sales, // Enable data label dataLabelSettings: DataLabelSettings(isVisible: true)) ]), ); } }
Screenshots
Border radius customization using extendibility
For more information on onCreateRenderer property, please click here.