Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Is it possible to add marker/tooltip on line chart and bar chart? #58

Closed
oneeall opened this issue May 21, 2018 · 83 comments
Closed

Is it possible to add marker/tooltip on line chart and bar chart? #58

oneeall opened this issue May 21, 2018 · 83 comments

Comments

@oneeall
Copy link

oneeall commented May 21, 2018

I have intention on looking for a specific point in a line chart of charts_flutter and then display the the marker to highlight the point after a points or bar is hit.

My question is, Is it possible to create a widget or add some label to the line chart and bar chart?

below is based on the my line chart example, on android apps
screen shot 2018-05-21 at 15 06 20

@lorrainekan
Copy link
Contributor

We don't yet have a timeline for adding touch cards.

@Winghin2517
Copy link

screen shot 2018-08-12 at 17 19 48

The graph as it stands has a vertical line that shows the place where the user has clicked on the graph. It would make sense for a marker to be place above the line similar to this:

screen shot 2018-08-12 at 17 22 55

@arlindiDev
Copy link

@oneeall did you find a solution to add the label where the user has selected a point in the graph ?

@krishnakumarcn
Copy link

Is this issue resolved?

@komputerboy
Copy link

any news about this?

@stasgora
Copy link

stasgora commented May 2, 2019

It can be done, although it took me some time to figure out.
Screenshot_20190502-154757~2
To get the value I used SelectionModelConfig.changedListener.

Now for the tricky part: I extended 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)

EDIT: Since my initial comment I have received several questions asking for a deeper explanation so I put together an example widget class:

Expand flutter chart label example
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);
}

@joaquinperaza
Copy link

@stasgora But how to display the value, not the fixed "1"?

@stasgora
Copy link

@joaquinperaza just create simple one variable model, pass it to the CustomCircleSymbolRenderer on creation and update in changedListener

@joaquinperaza
Copy link

Thank you!

@zarulizham
Copy link

zarulizham commented May 14, 2019

I've tried your code, seems it working for hardcoded String. I wrap setState the updated value like below:

changedListener: (charts.SelectionModel model) {
    if(model.hasDatumSelection) {
        setState(() {
            textSelected = (model.selectedSeries[0].measureFn(model.selectedDatum[0].index)).toString();  
        });
        debugPrint(textSelected);
    }
}

Then, the custom circle appear and disappear automatically in 1s.

This my constructor in CustomCircleSymbolRenderer class

String text;

CustomCircleSymbolRenderer(
    {String text}
) { this.text = text; }

This is the behaviour looks like: https://imgur.com/8CwRKme

@stasgora
Copy link

Yes, it does that. It is due to the fact that setState() causes the widget to rebuild and after that the selection is lost. To preserve it you have to manually set it in build method using InitialSelection.

@zarulizham
Copy link

I tried to use these two combination of behaviors,

      behaviors: [
        new charts.InitialSelection(selectedDataConfig: [
          new charts.SeriesDatumConfig<String>('Clicks', '2021')
        ]),
        new charts.LinePointHighlighter(
          symbolRenderer: CustomCircleSymbolRenderer(text: textSelected)
        ),
      ],

It seems crash. Crash log: https://pastebin.com/4i8x30tG

@pockyzhang
Copy link

Sir
have you tried to implement it ?any code thanks!!

@pockyzhang
Copy link

ok i figured out.
add String text; to CustomCircleSymbolRenderer
add CustomCircleSymbolRenderer render; to State
change render.text = selectedText; in setState

@k3v1n-uncle
Copy link

@pockyzhang 什么意思,能给个完整的页面demo吗

@kamlesh9070
Copy link

@stasgora
Is there any way can I display labels on line chart without click, means It should automatically display?

@rrnicolay
Copy link

rrnicolay commented Jul 8, 2019

ok i figured out.
add String text; to CustomCircleSymbolRenderer
add CustomCircleSymbolRenderer render; to State
change render.text = selectedText; in setState

Thanks for the comment. But it didn't worked for me. render.text always get the right value (inside setState()), but the tooltip never appear.
Edit: worked after removing the defaultRenderer.

@celiyawong
Copy link

The graph should show the label when it is displayed. No display is meaningless to the user.

@celiyawong
Copy link

Moreover, there is no Bezier curve.

@kamlesh9070
Copy link

kamlesh9070 commented Jul 22, 2019

For Bar Graph, I hv implemented my custom label decorator which display labels on vertical bar chart:
https://github.com/milanvadher/sadhana_revamp/blob/master/lib/charts/custom_bar_label_decorator.dart

To Use:
defaultRenderer: new BarRendererConfig<String>( strokeWidthPx: 0.3, barRendererDecorator: CustomBarLabelDecorator<String>(labelAnchor: CustomBarLabelAnchor.end), ),

@harshaIOT
Copy link

@joaquinperaza just create simple one variable model, pass it to the CustomCircleSymbolRenderer on creation and update in changedListener

I have done the same thing but the value of the text is not updating, please help me

@drafting-dreams
Copy link

@stasgora Great work! Now I have two or more series in one chart. This will show symbols near all series. I wanna get all the data from each series into one variable. And only show one tooltip near one of the series. How can I achieve that?

@anweramindev
Copy link

@stasgora Great work! Now I have two or more series in one chart. This will show symbols near all series. I wanna get all the data from each series into one variable. And only show one tooltip near one of the series. How can I achieve that?

I am essentially looking for the same, I have multiple series? any luck figuring this out?

I am using the selection callback to just display the values in a card below the chart at the moment.

@Toby14
Copy link

Toby14 commented Nov 15, 2020

Hi,
did anyone figure out how to show labels on line chart yet without clicking?

What about showing the values when you click on the graph? I have done this

@Shtille
Copy link

Shtille commented Nov 25, 2020

Hi,
did anyone figure out how to show labels on line chart yet without clicking?

What about showing the values when you click on the graph? I have done this

Have you done with tooltips for chart?

@hieuplasma
Copy link

@pockyzhang 什么意思,能给个完整的页面demo吗

English pls, no one can understand

@skajarekar-cci
Copy link

Hi,
did anyone figure out how to show labels on line chart yet without clicking?

What about showing the values when you click on the graph? I have done this

How to do this ?

@jeffersonmello
Copy link

thanks everyone! I did it ❤️

image

here are some snippets:

final size = MediaQuery.of(context).size;

//---
behaviors: [
        charts.SeriesLegend(
          position: charts.BehaviorPosition.top,
          horizontalFirst: false,
          desiredMaxRows: 2,
          cellPadding: EdgeInsets.only(right: 4.0, bottom: 4.0),
        ),
        charts.SelectNearest(
          eventTrigger: charts.SelectionTrigger.tapAndDrag
        ),
        charts.LinePointHighlighter(
          symbolRenderer: CustomCircleSymbolRenderer(size: size),
        ),
 ],
selectionModels: [
        charts.SelectionModelConfig(
          type: charts.SelectionModelType.info,
          changedListener: (charts.SelectionModel model) {
            if (model.hasDatumSelection) {
              selectedDatum = [];
              model.selectedDatum.forEach((charts.SeriesDatum datumPair) {
                selectedDatum.add({
                  'color': datumPair.series.colorFn(0),
                  'text': '${datumPair.datum.x}: ${datumPair.datum.y}'
                });
              });
            }
          }
        )
      ],

//---
class CustomCircleSymbolRenderer extends charts.CircleSymbolRenderer {
  final size;

  CustomCircleSymbolRenderer({ this.size });

  @override
  void paint(charts.ChartCanvas canvas, Rectangle bounds, {
    List dashPattern,
    charts.Color fillColor,
    charts.FillPatternType fillPattern,
    charts.Color strokeColor,
    double strokeWidthPx
  }) {
    super.paint(
      canvas,
      bounds,
      dashPattern: dashPattern,
      fillColor: fillColor,
      strokeColor: strokeColor,
      strokeWidthPx: strokeWidthPx
    );

    List tooltips = _LineChartWidgetState.selectedDatum;
    String unit = _LineChartWidgetState.unit;
    if (tooltips != null && tooltips.length > 0) {
      num tipTextLen = (tooltips[0]['text'] + unit).length;
      num rectWidth = bounds.width + tipTextLen * 8.3;
      num rectHeight = bounds.height + 20 + (tooltips.length - 1) * 18;
      num left = bounds.left > (size?.width ?? 300) / 2
        ? (bounds.left > size?.width / 4 ? bounds.left - rectWidth : bounds.left - rectWidth / 2)
        : bounds.left - 40;

      canvas.drawRect(
        Rectangle(left, 0, rectWidth, rectHeight),
        fill: charts.Color.fromHex(code: '#666666')
      );

      for (int i = 0; i < tooltips.length; i++) {
        canvas.drawPoint(
          point: Point(left.round() + 8, (i + 1) * 15),
          radius: 3,
          fill: tooltips[i]['color'],
          stroke: charts.Color.white,
          strokeWidthPx: 1,
        );
        chartStyle.TextStyle textStyle = chartStyle.TextStyle();
        textStyle.color = charts.Color.white;
        textStyle.fontSize = 13;
        canvas.drawText(chartText.TextElement(tooltips[i]['text'] + unit, style: textStyle), left.round() + 15, i * 15 + 8);
      }
    }
  }
}

you can post full example?

@deep-iconflux
Copy link

class CustomCircleSymbolRenderer extends charts.CircleSymbolRenderer {
final size;

CustomCircleSymbolRenderer({ this.size });

@OverRide
void paint(charts.ChartCanvas canvas, Rectangle bounds, {
List dashPattern,
charts.Color fillColor,
charts.FillPatternType fillPattern,
charts.Color strokeColor,
double strokeWidthPx
}) {
super.paint(
canvas,
bounds,
dashPattern: dashPattern,
fillColor: fillColor,
strokeColor: strokeColor,
strokeWidthPx: strokeWidthPx
);

List tooltips = _LineChartWidgetState.selectedDatum;
String unit = _LineChartWidgetState.unit;
if (tooltips != null && tooltips.length > 0) {
  num tipTextLen = (tooltips[0]['text'] + unit).length;
  num rectWidth = bounds.width + tipTextLen * 8.3;
  num rectHeight = bounds.height + 20 + (tooltips.length - 1) * 18;
  num left = bounds.left > (size?.width ?? 300) / 2
    ? (bounds.left > size?.width / 4 ? bounds.left - rectWidth : bounds.left - rectWidth / 2)
    : bounds.left - 40;

  canvas.drawRect(
    Rectangle(left, 0, rectWidth, rectHeight),
    fill: charts.Color.fromHex(code: '#666666')
  );

  for (int i = 0; i < tooltips.length; i++) {
    canvas.drawPoint(
      point: Point(left.round() + 8, (i + 1) * 15),
      radius: 3,
      fill: tooltips[i]['color'],
      stroke: charts.Color.white,
      strokeWidthPx: 1,
    );
    chartStyle.TextStyle textStyle = chartStyle.TextStyle();
    textStyle.color = charts.Color.white;
    textStyle.fontSize = 13;
    canvas.drawText(chartText.TextElement(tooltips[i]['text'] + unit, style: textStyle), left.round() + 15, i * 15 + 8);
  }
}

}
}

Can you please post full example?

@guiinfo3333
Copy link

CustomCircleSymbolRenderer.value = ;

saved me, thank you very much!

@letica
Copy link

letica commented Mar 5, 2021

@jeffersonmello sorry, I'm not use this tool just now. For me, flutter_echarts is more friendly.

@tnusraddinov
Copy link

tnusraddinov commented Mar 23, 2021

@letica
flutter_echarts is good lib, but in ios sometimes charts are not rendered.

@dakshpokar
Copy link

I added tooltip but is there a way to hide it? Also it seems that there is some problem when SlidingViewport is enabled.
When you select a bar and tooltip is shown, Sliding is stuck.

@zxc-cool
Copy link

zxc-cool commented Apr 14, 2021

I need to add a click event to it, how do I change it.
image

@shatanikmahanty
Copy link

Hi tried the solutions given by everyone but in bar charts having two sets of data the tooltip gets drawn twice .

I am attaching a screenshot below for reference. Can anyone help me solve it.

Screenshot_20210417-234125

Code :

selectionModels: [
        charts.SelectionModelConfig(
            type: charts.SelectionModelType.info,
            updatedListener: (model) {},
            changedListener: (charts.SelectionModel model) {
              if (model.hasDatumSelection) {
                selectedDatum = [];
                model.selectedDatum.forEach((charts.SeriesDatum datumPair) {
                  selectedDatum.add({
                    'color': datumPair.series.colorFn(0),
                    'text': '${datumPair.datum.sales}'
                  });
                });
                print(selectedDatum);
              } else {
                selectedDatum = [];
              }
            })
      ],
behaviors: [
        charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag),
        charts.LinePointHighlighter(
          symbolRenderer: new CustomCircleSymbolRenderer(size: size),
        ),
        charts.SeriesLegend.customLayout(
          CustomLegendBuilder(title, sub, width),
          // Other legend properties here
        ),
        new charts.ChartTitle("",
            behaviorPosition: charts.BehaviorPosition.bottom,
            titleOutsideJustification: charts.OutsideJustification.middle,
            innerPadding: 10),
      ],

CustomSymbolRenderer :

class CustomCircleSymbolRenderer extends charts.CircleSymbolRenderer {
  final Size size;

  CustomCircleSymbolRenderer({this.size});

  @override
  void paint(charts.ChartCanvas canvas, Rectangle bounds,
      {List dashPattern,
      charts.Color fillColor,
      charts.FillPatternType fillPattern,
      charts.Color strokeColor,
      double strokeWidthPx}) {
    super.paint(
      canvas,
      bounds,
      dashPattern: dashPattern,
      fillColor: fillColor,
      strokeColor: strokeColor,
      strokeWidthPx: strokeWidthPx,
    );

    List tooltips = _DashboardState.selectedDatum;
    // String unit = _DashboardState.unit;
    if (tooltips != null && tooltips.length > 0) {
      num tipTextLen = (tooltips[0]['text']).length;
      num rectWidth = bounds.width + tipTextLen * 8.3;
      num rectHeight = bounds.height + 20 + (tooltips.length - 1) * 18;
      num left = bounds.left > (size.width ?? 300) / 2
          ? (bounds.left > size.width / 4
              ? bounds.left - rectWidth
              : bounds.left - rectWidth / 2)
          : bounds.left;

      canvas.drawRect(
        Rectangle(left, 0, rectWidth, rectHeight),
        fill: charts.Color.fromHex(code: '#666666'),
      );

      for (int i = 0; i < tooltips.length; i++) {
        canvas.drawPoint(
          point: Point(left.round() + 8, (i + 1) * 15),
          radius: 3,
          fill: tooltips[i]['color'],
          stroke: charts.Color.white,
          strokeWidthPx: 1,
        );
        chartStyle.TextStyle textStyle = chartStyle.TextStyle();
        textStyle.color = charts.Color.white;
        textStyle.fontSize = 13;
        canvas.drawText(
            chartText.TextElement(tooltips[i]['text'], style: textStyle),
            left.round() + 15,
            i * 15 + 8);
      }
    }
  }
}

@randhika
Copy link

when touch on the red line, the value shows on the blue, please help
WhatsApp Image 2020-03-05 at 17 59 38

Hi Sarah, I have 2 sales data like you, but the tooltips show double. How can I hide second tooltips if I have more than data series in the chart?

Thanks

@randhika
Copy link

randhika commented Apr 27, 2021

Hey guys, I have a problem with tooltips when reading multiple series in the chart. Can we hide the second tooltips and just show 1 tooltip with combine data?

Thanks

Screen Shot 2021-04-27 at 12 19 53

@madrainbo
Copy link

The issue is open since 2018. Is it fixed in the recent release?

@Renatinaveen
Copy link

The issue is open since 2018. Is it fixed in the recent release?

Could you share an example?

@oneeall oneeall closed this as completed Jun 22, 2021
@minamakhtar
Copy link

@randhika any solution for your problem?

@Renatinaveen
Copy link

@M1chlCZ
Copy link

M1chlCZ commented Jul 16, 2021

@Renatinaveen You are missing there CustomRectangleSymbolRenderer piece of code.

@Renatinaveen
Copy link

@M1chlCZ thanks. It's updated please check it out.

@NguyenDinhThai
Copy link

thanks everyone! I did it ❤️
image
here are some snippets:

final size = MediaQuery.of(context).size;

//---
behaviors: [
        charts.SeriesLegend(
          position: charts.BehaviorPosition.top,
          horizontalFirst: false,
          desiredMaxRows: 2,
          cellPadding: EdgeInsets.only(right: 4.0, bottom: 4.0),
        ),
        charts.SelectNearest(
          eventTrigger: charts.SelectionTrigger.tapAndDrag
        ),
        charts.LinePointHighlighter(
          symbolRenderer: CustomCircleSymbolRenderer(size: size),
        ),
 ],
selectionModels: [
        charts.SelectionModelConfig(
          type: charts.SelectionModelType.info,
          changedListener: (charts.SelectionModel model) {
            if (model.hasDatumSelection) {
              selectedDatum = [];
              model.selectedDatum.forEach((charts.SeriesDatum datumPair) {
                selectedDatum.add({
                  'color': datumPair.series.colorFn(0),
                  'text': '${datumPair.datum.x}: ${datumPair.datum.y}'
                });
              });
            }
          }
        )
      ],

//---
class CustomCircleSymbolRenderer extends charts.CircleSymbolRenderer {
  final size;

  CustomCircleSymbolRenderer({ this.size });

  @override
  void paint(charts.ChartCanvas canvas, Rectangle bounds, {
    List dashPattern,
    charts.Color fillColor,
    charts.FillPatternType fillPattern,
    charts.Color strokeColor,
    double strokeWidthPx
  }) {
    super.paint(
      canvas,
      bounds,
      dashPattern: dashPattern,
      fillColor: fillColor,
      strokeColor: strokeColor,
      strokeWidthPx: strokeWidthPx
    );

    List tooltips = _LineChartWidgetState.selectedDatum;
    String unit = _LineChartWidgetState.unit;
    if (tooltips != null && tooltips.length > 0) {
      num tipTextLen = (tooltips[0]['text'] + unit).length;
      num rectWidth = bounds.width + tipTextLen * 8.3;
      num rectHeight = bounds.height + 20 + (tooltips.length - 1) * 18;
      num left = bounds.left > (size?.width ?? 300) / 2
        ? (bounds.left > size?.width / 4 ? bounds.left - rectWidth : bounds.left - rectWidth / 2)
        : bounds.left - 40;

      canvas.drawRect(
        Rectangle(left, 0, rectWidth, rectHeight),
        fill: charts.Color.fromHex(code: '#666666')
      );

      for (int i = 0; i < tooltips.length; i++) {
        canvas.drawPoint(
          point: Point(left.round() + 8, (i + 1) * 15),
          radius: 3,
          fill: tooltips[i]['color'],
          stroke: charts.Color.white,
          strokeWidthPx: 1,
        );
        chartStyle.TextStyle textStyle = chartStyle.TextStyle();
        textStyle.color = charts.Color.white;
        textStyle.fontSize = 13;
        canvas.drawText(chartText.TextElement(tooltips[i]['text'] + unit, style: textStyle), left.round() + 15, i * 15 + 8);
      }
    }
  }
}

This example from letica works good.

My question: does anyone know how to give the rectangle's corners a radius? Can't find anything.

Screenshot 2020-10-02 at 22 35 01

PS: I used provider to add the datum to my list, sort the pair, and consume the list again in the drawText section of the example.

'

          selectionModels: [
            SelectionModelConfig(
              type: charts.SelectionModelType.info,
              changedListener: (SelectionModel model) {
                if (model.hasDatumSelection) {
                  salesChartService.selectedDatum.clear();
                  model.selectedDatum.forEach((charts.SeriesDatum datumPair) {
                    salesChartService.selectedDatum.add({
                      'color': datumPair.series.colorFn(0),
                      'text': 'R${datumPair.datum.amount}',
                    });
                  });
                  salesChartService.selectedDatum.sort((a, b) {
                    return b['color'].toString().toLowerCase().compareTo(a['color'].toString().toLowerCase());
                  });
                }
              },
            )
          ]

`
How do you use canvas.drawText(chartText.TextElement(tooltips[i]['text'] + unit, style: textStyle), left.round() + 15, i * 15 + 8);
By import:
import 'package:charts_flutter/src/text_element.dart' as TextElement;
import 'package:charts_flutter/src/text_style.dart' as style;
I saw this recommend :Don't import implementation files from another package.It is safe

@YorekLiu
Copy link

YorekLiu commented Jan 27, 2022

CustomCircleSymbolRender receive a String Function() parameters, can also solve this problem. So, symbolRender will draw the dynamic text given by String Function().

This is the full example:

test_page.dart

import 'dart:math';
import 'package:flutter/painting.dart' as painting;

import 'package:charts_flutter/flutter.dart';
import 'package:f_wallet/widget/text_symbol_renderer.dart';
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts hide Color;

class TestModePage extends StatefulWidget {
  const TestModePage({Key? key}) : super(key: key);

  @override
  State<TestModePage> createState() => _TestModePageState();
}

class _TestModePageState extends State<TestModePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TestMode'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: AspectRatio(
          aspectRatio: 1,
          child: Container(
            padding: const EdgeInsets.all(16),
            child: PointsLineChart.withSampleData(),
            decoration: const ShapeDecoration(
              color: painting.Color(0xFFDBE1F1),
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
            ),
          )
        ),
      ),
    );
  }
}

class PointsLineChart extends StatelessWidget {
  final List<charts.Series<LinearSales, int>> seriesList;
  final bool animate;

  PointsLineChart(this.seriesList, {required this.animate});

  /// Creates a [LineChart] with sample data and no transition.
  factory PointsLineChart.withSampleData() {
    return new PointsLineChart(
      _createSampleData(),
      // Disable animations for image tests.
      animate: false,
    );
  }


  @override
  Widget build(BuildContext context) {
    return new charts.LineChart(seriesList,
        animate: animate,
        defaultRenderer: new charts.LineRendererConfig(includePoints: true),
        behaviors: [
          charts.LinePointHighlighter(
            ////////////////////// notice ////////////////////////////
            symbolRenderer: TextSymbolRenderer(() => Random().nextInt(100).toString()),
            ////////////////////// notice ////////////////////////////
          ),
        ],
    );
  }

  /// Create one series with sample hard coded data.
  static List<charts.Series<LinearSales, int>> _createSampleData() {
    final data = [
      new LinearSales(0, 5),
      new LinearSales(1, 25),
      new LinearSales(2, 100),
      new LinearSales(3, 75),
    ];

    return [
      new charts.Series<LinearSales, int>(
        id: 'Sales',
        colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
        domainFn: (LinearSales sales, _) => sales.year,
        measureFn: (LinearSales sales, _) => sales.sales,
        data: data,
      )
    ];
  }
}

/// Sample linear data type.
class LinearSales {
  final int year;
  final int sales;

  LinearSales(this.year, this.sales);
}

text_symbol_render.dart

import 'dart:developer' as developer;
import 'dart:math';

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

typedef GetText = String Function();

class TextSymbolRenderer extends CircleSymbolRenderer {

  TextSymbolRenderer(this.getText, {this.marginBottom = 8, this.padding = const EdgeInsets.all(8)});

  final GetText getText;
  final double marginBottom;
  final EdgeInsets padding;


  @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);

    style.TextStyle textStyle = style.TextStyle();
    textStyle.color = Color.black;
    textStyle.fontSize = 15;

    element.TextElement textElement = element.TextElement(getText.call(), style: textStyle);
    double width = textElement.measurement.horizontalSliceWidth;
    double height = textElement.measurement.verticalSliceWidth;

    double centerX = bounds.left + bounds.width / 2;
    double centerY = bounds.top + bounds.height / 2 - marginBottom - (padding.top + padding.bottom);

    canvas.drawRRect(
        Rectangle(
            centerX - (width / 2) - padding.left,
            centerY - (height / 2) - padding.top,
            width + (padding.left + padding.right),
            height + (padding.top + padding.bottom),
        ),
        fill: Color.white,
        radius: 16,
        roundTopLeft: true,
        roundTopRight: true,
        roundBottomRight: true,
        roundBottomLeft: true,
    );
    canvas.drawText(
        textElement,
        (centerX - (width / 2)).round(),
        (centerY - (height / 2)).round(),
    );
  }
}

The picture is there:
Screenshot_20220127_171136

@syomna
Copy link

syomna commented Mar 30, 2022

@YorekLiu I tried it and it works but when I'm getting the actual data the first element of the list from changedListener using bloc and trying to pass it to the text renderer it doesn't appear on the chart anymore while the string in bloc has the data

@amirVirtuenetz
Copy link

amirVirtuenetz commented Jun 10, 2022

i want to make the same chart in flutter to show yearly activity on the base of data like this
[
{total:2,days:[0,0,0,0,1,2,,5]},
{total:5,days:[0,0,0,0,1,2,,5]},
{total:6,days:[0,0,0,0,1,2,,5]}, --> this represent the one week of month data also and much more data like this
]
how can i display in a line chart graph in flutter?

@ljmatan
Copy link

ljmatan commented Jul 13, 2022

@YorekLiu points are overlaid over the numbers

Screenshot 2022-07-13 at 20 34 36

@cheadevit
Copy link

@ljmatan Could you please share code example?

@ljmatan
Copy link

ljmatan commented Jul 14, 2022

@cheadevit https://github.com/ljmatan/mingo

There's no API in there so you won't be able to compile it though, you can take a look at the chart_section.dart file and YorekLiu's comment.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests