Drawing Custom Shape for label of SfCartesianChart flutter

118 views Asked by At

I want to draw a shape for the label of the axis like the following image when the user clicks on the chart.

enter image description here

My code for drawing this chart is:

SfCartesianChart(
   plotAreaBorderWidth: 0,
   trackballBehavior: _trackballBehavior,
   palette: const <Color>[AppColors.primary500],
   onTrackballPositionChanging: (TrackballArgs args) {
   },
   primaryYAxis: const NumericAxis(
     interval: 5,
     edgeLabelPlacement: EdgeLabelPlacement.hide,
     isVisible: false,
     majorGridLines: MajorGridLines(width: 0),
     rangePadding: ChartRangePadding.auto,
   ),
   primaryXAxis: CategoryAxis(
     axisLine: AxisLine(width: 1, color: theme.cardColor),
     majorTickLines: const MajorTickLines(size: 0),
     majorGridLines: const MajorGridLines(
     width: 1,
     color: AppColors.gray200,
     dashArray: <double>[5, 5],
   ),
   rangePadding: ChartRangePadding.auto,
   labelPlacement: LabelPlacement.onTicks,
   labelStyle: theme.textTheme.titleSmall!.copyWith(color: AppColors.gray500),
   ),
   series: <CartesianSeries>[
     SplineSeries<ChartData, String>(
     dataSource: chartData,
     animationDuration: 0,
     splineType: SplineType.cardinal,
     cardinalSplineTension: 0.9,
     xValueMapper: (ChartData data, _) => data.x,
     yValueMapper: (ChartData data, _) => data.y)
    ],
   ),
1

There are 1 answers

0
Preethika Selvam On

You can achieve your requirement by using ‘onDataLabelTapped’ callback to handle tap events on the data labels and update the ‘selectedAxisLabel’. By using ‘selectedAxisLabel’, we have checked the current axis label text with the selected axis label text and updated the axis label based on the ‘selectedAxisLable’. Additionally we utilized ‘axisLabelFormatter’ callback to alter the style of the selected axis label. We have shared a code snippet, and a sample for your reference. You can modify the sample based on your needs.

late String selectedAxisLabel;

  @override
  void initState() {
    _trackballBehavior = TrackballBehavior(
      enable: true,
    );
    selectedAxisLabel = '';
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final List<ChartData> chartData = [
      ChartData('Jan', 35, 53),
      ChartData('Feb', 46, 36),
      ChartData('Mar', 46, 56),
      ChartData('Apr', 50, 86),
      ChartData('May', 60, 89),
      ChartData('Jun', 70, 27),
      ChartData('Jul', 75, 65),
      ChartData('Aug', 74, 70),
    ];

    return Scaffold(
      body: Center(
        child: SfCartesianChart(
          onDataLabelTapped: (onTapArgs) {
            setState(() {
              selectedAxisLabel = chartData[onTapArgs.pointIndex].x;
            });
          },
          backgroundColor: Colors.grey.shade300,
          plotAreaBorderWidth: 0,
          trackballBehavior: _trackballBehavior,
          onTrackballPositionChanging: (TrackballArgs args) {},
          primaryYAxis: const NumericAxis(
            interval: 5,
            edgeLabelPlacement: EdgeLabelPlacement.hide,
            isVisible: false,
            majorGridLines: MajorGridLines(width: 0),
            rangePadding: ChartRangePadding.auto,
          ),
          primaryXAxis: CategoryAxis(
            axisLabelFormatter: (axisLabelRenderArgs) {
              return axis(axisLabelRenderArgs);
            },
            axisLine: const AxisLine(
              width: 0,
              color: Colors.grey,
            ),
            majorTickLines: const MajorTickLines(size: 0),
            majorGridLines: const MajorGridLines(
              width: 1,
              color: Colors.grey,
              dashArray: <double>[5, 5],
            ),
            rangePadding: ChartRangePadding.auto,
            labelPlacement: LabelPlacement.onTicks,
          ),
          series: <CartesianSeries>[
            SplineSeries<ChartData, String>(
                dataLabelSettings: const DataLabelSettings(
                  isVisible: true,
                  color: Colors.blue,
                  borderRadius: 9,
                ),
                markerSettings: const MarkerSettings(
                    isVisible: true, color: Colors.blue, width: 10, height: 10),
                dataSource: chartData,
                animationDuration: 0,
                width: 4,
                color: Colors.blue,
                splineType: SplineType.cardinal,
                cardinalSplineTension: 0.9,
                dataLabelMapper: (ChartData data, _) => data.x,
                xValueMapper: (ChartData data, _) => data.x,
                yValueMapper: (ChartData data, _) => data.y)
          ],
        ),
      ),
    );
  }

  ChartAxisLabel axis(AxisLabelRenderDetails details) {
    if (details.text == selectedAxisLabel) {
      return ChartAxisLabel(
          "${details.text} 2024",
          const TextStyle(
            color: Colors.white,
            backgroundColor: Colors.blue,
          ));
    } else {
      return ChartAxisLabel(details.text, details.textStyle);
    }
  }