How to display data value of an item on click inside flutter charts

11,913

Solution 1

Found a solution from Github issues

https://github.com/google/charts/issues/58

To get the value use SelectionModelConfig.changedListener.

Extend the CircleSymbolRenderer (for LinePointHighlighter.symbolRenderer) and overridden the paint method. Inside you can draw custom objects relative to the selected point.

Maybe in the future the authors will make this easier but for now you use this method to modify rendering process of the selected point in any way you need (using ChartCanvas methods)

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart';
import 'package:charts_flutter/src/text_element.dart';
import 'package:charts_flutter/src/text_style.dart' as style;

class Chart extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LineChart(
      _createSampleData(),
      behaviors: [
        LinePointHighlighter(
          symbolRenderer: CustomCircleSymbolRenderer()
        )
      ],
      selectionModels: [
        SelectionModelConfig(
          changedListener: (SelectionModel model) {
            if(model.hasDatumSelection)
              print(model.selectedSeries[0].measureFn(model.selectedDatum[0].index));
          }
        )
      ],
    );
  }

  List<Series<LinearSales, int>> _createSampleData() {
    final data = [
      new LinearSales(0, 5),
      new LinearSales(1, 25),
      new LinearSales(2, 100),
      new LinearSales(3, 75),
    ];
    return [
      new Series<LinearSales, int>(
        id: 'Sales',
        colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
        domainFn: (LinearSales sales, _) => sales.year,
        measureFn: (LinearSales sales, _) => sales.sales,
        data: data,
      )
    ];
  }
}

class CustomCircleSymbolRenderer extends CircleSymbolRenderer {
  @override
  void paint(ChartCanvas canvas, Rectangle<num> bounds, {List<int> dashPattern, Color fillColor, Color strokeColor, double strokeWidthPx}) {
    super.paint(canvas, bounds, dashPattern: dashPattern, fillColor: fillColor, strokeColor: strokeColor, strokeWidthPx: strokeWidthPx);
    canvas.drawRect(
      Rectangle(bounds.left - 5, bounds.top - 30, bounds.width + 10, bounds.height + 10),
      fill: Color.white
    );
    var textStyle = style.TextStyle();
    textStyle.color = Color.black;
    textStyle.fontSize = 15;
    canvas.drawText(
      TextElement("1", style: textStyle),
        (bounds.left).round(),
        (bounds.top - 28).round()
    );
  }
}
class LinearSales {
  final int year;
  final int sales;
  LinearSales(this.year, this.sales);
}

Solution 2

There were some errors when using the ChartCanvas method above the modified corrected version of this code is:

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart';
// import 'package:charts_flutter/src/chart_canvas.dart' as eos;
import 'package:charts_flutter/src/text_element.dart' as TextElement;
import 'package:charts_flutter/src/text_style.dart' as style;

class Chart extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LineChart(
      _createSampleData(),
      behaviors: [
        LinePointHighlighter(
          symbolRenderer: CustomCircleSymbolRenderer()
        )
      ],
      selectionModels: [
        SelectionModelConfig(
          changedListener: (SelectionModel model) {
            if(model.hasDatumSelection)
              print(model.selectedSeries[0].measureFn(model.selectedDatum[0].index));
          }
        )
      ],
    );
  }

  List<Series<LinearSales, int>> _createSampleData() {
    final data = [
      new LinearSales(0, 5),
      new LinearSales(1, 25),
      new LinearSales(2, 100),
      new LinearSales(3, 75),
    ];
    return [
      new Series<LinearSales, int>(
        id: 'Sales',
        colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
        domainFn: (LinearSales sales, _) => sales.year,
        measureFn: (LinearSales sales, _) => sales.sales,
        data: data,
      )
    ];
  }
}

class CustomCircleSymbolRenderer extends CircleSymbolRenderer {

  @override
  void paint(ChartCanvas canvas, Rectangle<num> bounds, {List<int> dashPattern, Color fillColor, FillPatternType fillPattern, Color strokeColor, double strokeWidthPx}) {
    super.paint(canvas, bounds, dashPattern: dashPattern, fillColor: fillColor,fillPattern: fillPattern, strokeColor: strokeColor, strokeWidthPx: strokeWidthPx);
    canvas.drawRect(
      Rectangle(bounds.left - 5, bounds.top - 30, bounds.width + 10, bounds.height + 10),
      fill: Color.white
    );
    var textStyle = style.TextStyle();
    textStyle.color = Color.black;
    textStyle.fontSize = 15;
    canvas.drawText(

      TextElement.TextElement("1", style: textStyle),
        (bounds.left).round(),
        (bounds.top - 28).round()
    );
  }
}
class LinearSales {
  final int year;
  final int sales;
  LinearSales(this.year, this.sales);
}

Solution 3

I think you are searching for selection model, here is a bit of code which make event happened when you touch in chart:

selectionModels: [
    new charts.SelectionModelConfig(
        changedListener: (SelectionModel model) {
            print( model.selectedSeries[0].measureFn(
                model.selectedDatum[0].index);
        }
    )
],
Share:
11,913

Related videos on Youtube

krishnakumarcn
Author by

krishnakumarcn

Engineer. Flutter Evangelist

Updated on June 04, 2022

Comments

  • krishnakumarcn
    krishnakumarcn almost 2 years

    I'm using charts_flutter library on one of my projects and I would like to display the data value on clicking on each Bar chart item. Is it possible?

    var data = [
      new ClicksPerYear('2016', 12, Colors.red),
      new ClicksPerYear('2017', 42, Colors.blue),
      new ClicksPerYear('2018', counter, Colors.green),
    ];
    
    var series = [
      new charts.Series(
        id: 'Clicks',
        data: data,
        domainFn: (ClicksPerYear clickData, _) => clickData.year,
        measureFn: (ClicksPerYear clickData, _) => clickData.clicks,
        colorFn: (ClicksPerYear clickData, _) => clickData.color,
      )
    ];
    var barChart = new charts.BarChart(
          series,
          animate: true,
    );
    
  • krishnakumarcn
    krishnakumarcn about 5 years
    Its not about the seletion. Its about the painting inside the chart library.
  • Harsha Vardhan
    Harsha Vardhan over 4 years
    How will you update the value for TextElement, when you can't use setState in CustomCircleSymbolRenderer please help me out
  • Mahesh Jamdade
    Mahesh Jamdade over 3 years
    place the widget in build method
  • Bharat Chhabra
    Bharat Chhabra over 3 years
    How to access and show the value of the chart instead of a "1" in CustomCircleSymbolRenderer?
  • Timo Bähr
    Timo Bähr about 3 years
    @bharat-chhabra I just updated this answer to make it clear how to draw the value. Hopefully approved soon.
  • David L
    David L about 3 years
    Thank you. It can print the y axis value. What do I need to for printing the x axis value?