How to Customize Trackball Marker Colors for Individual Series in Flutter Charts
The TrackballBehavior supports the onPaint public method to customize the marker, label, position, and style of the trackball tooltip.
In this article, we will explain how to set different marker colors for each data point in the trackball tooltip by extending the TrackballBehavior and using its public methods in Flutter CartesianChart .
The chartPointInfo field in the TrackballBehavior provides access to the position of the trackball and allows you to customize how markers are drawn along with the trackball. You can override the onPaint method to render markers with different colors.
The following steps explain how to customize the marker colors for the trackball.
Step 1: Initialize the list chartData1 and chartData2 as your data sources. Then, create a RangeData class to hold the x, low, and high values for each data point. Finally, build the SfCartesianChart widget using the RangeColumnSeries and set the dataSource property to chartData1 and chartData2. The xValueMapper, lowValueMapper, and highValueMapper properties map the respective values.
final List<RangeData> chartData1 = [
RangeData(x: 'Product A', low: 10, high: 100),
RangeData(x: 'Product B', low: 20, high: 120),
RangeData(x: 'Product C', low: 10, high: 150),
RangeData(x: 'Product D', low: 20, high: 120),
RangeData(x: 'Product E', low: 10, high: 140),
];
final List<RangeData> chartData2 = [
RangeData(x: 'Product A', low: 10, high: 100),
RangeData(x: 'Product B', low: 20, high: 120),
RangeData(x: 'Product C', low: 10, high: 150),
RangeData(x: 'Product D', low: 20, high: 120),
RangeData(x: 'Product E', low: 10, high: 140),
];
@override
Widget build(BuildContext context) {
return SfCartesianChart(
enableSideBySideSeriesPlacement: false,
primaryXAxis: const CategoryAxis(),
series: [
RangeColumnSeries<RangeData, String>(
dataSource: chartData1,
xValueMapper: (RangeData data, int index) => data.x,
lowValueMapper: (RangeData data, int index) => data.low,
highValueMapper: (RangeData data, int index) => data.high,
),
RangeColumnSeries<RangeData, String>(
dataSource: chartData2,
xValueMapper: (RangeData data, int index) => data.x,
lowValueMapper: (RangeData data, int index) => data.low,
highValueMapper: (RangeData data, int index) => data.high,
),
],
);
}
class RangeData {
RangeData({required this.x, required this.low, required this.high});
final String x;
final double low;
final double high;
}
Step 2: Create a _CustomTrackballBehavior class that extends the TrackballBehavior class. Here, we override the enable and activationMode properties to enable the trackball and set it to ActivationMode.singleTap. We also define the TrackballMarkerSettings to customize the appearance of the markers.
class _CustomTrackballBehavior extends TrackballBehavior {
@override
bool get enable => true;
@override
ActivationMode get activationMode => ActivationMode.singleTap;
@override
TrackballMarkerSettings? get markerSettings => const TrackballMarkerSettings(
markerVisibility: TrackballVisibilityMode.visible,
shape: DataMarkerType.diamond,
borderWidth: 1,
);
}
Step 3: Now, we will customize the colors of the markers by creating the _drawCustomMarker method. This method contains the logic for customizing and drawing markers at both the high and low positions for each data point. The fillPaint color is set using chartPointInfo color, and the markers are drawn at their respective calculated positions.
void _drawCustomMarker(PaintingContext context) {
if (chartPointInfo.isEmpty || parentBox == null) {
return;
}
final Paint fillPaint = Paint()..style = PaintingStyle.fill;
const Size lineMarkerSize = Size(15, 15);
final translatePos = Offset(-lineMarkerSize.width / 2, -lineMarkerSize.height / 2);
if (chartPointInfo.isNotEmpty) {
final int length = chartPointInfo.length;
for (int i = 0; i < length; i++) {
fillPaint.color = chartPointInfo[i].color!;
// High position marker.
Offset position = Offset(chartPointInfo[i].xPosition!, chartPointInfo[i].yPosition!);
paint(
canvas: context.canvas,
rect: position.translate(translatePos.dx, translatePos.dy) & lineMarkerSize,
shapeType: ShapeMarkerType.diamond,
paint: fillPaint,
);
// Low position marker.
position = Offset(chartPointInfo[i].xPosition!, chartPointInfo[i].lowYPosition!);
paint(
canvas: context.canvas,
rect: position.translate(translatePos.dx, translatePos.dy) & lineMarkerSize,
shapeType: ShapeMarkerType.diamond,
paint: fillPaint,
);
}
}
}
Step 4: Override the onPaint method of the TrackballBehavior class and call super onPaint to render the trackball, then use the _drawCustomMarker method to customize and draw each marker in the trackball tooltip with its assigned color.
@override
void onPaint(
PaintingContext context,
Offset offset,
SfChartThemeData chartThemeData,
ThemeData themeData,
) {
super.onPaint(context, offset, chartThemeData, themeData);
_drawCustomMarker(context);
}
Step 5: Initialize this _CustomTrackballBehavior class to TrackballBehavior property which is available in the SfCartesianChart.
@override
Widget build(BuildContext context) {
SfCartesianChart(
trackballBehavior: _CustomTrackballBehavior(),
.....
Now, the updated marker color for specific series in trackball functionality have been implemented as shown below.
Conclusion
I hope you enjoyed learning about how to customize the trackball marker color for a specific series in Flutter 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 forums, Direct-Trac, or feedback portal. We are always happy to assist you!