Closed oneeall closed 3 years ago
We don't yet have a timeline for adding touch cards.
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:
@oneeall did you find a solution to add the label where the user has selected a point in the graph ?
Is this issue resolved?
any news about this?
It can be done, although it took me some time to figure out.
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:
@stasgora But how to display the value, not the fixed "1"?
@joaquinperaza just create simple one variable model, pass it to the CustomCircleSymbolRenderer
on creation and update in changedListener
Thank you!
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
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
.
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
Sir have you tried to implement it ?any code thanks!!
ok i figured out. add String text; to CustomCircleSymbolRenderer add CustomCircleSymbolRenderer render; to State change render.text = selectedText; in setState
@pockyzhang 什么意思,能给个完整的页面demo吗
@stasgora Is there any way can I display labels on line chart without click, means It should automatically display?
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.
The graph should show the label when it is displayed. No display is meaningless to the user.
Moreover, there is no Bezier curve.
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), ),
@joaquinperaza just create simple one variable model, pass it to the
CustomCircleSymbolRenderer
on creation and update inchangedListener
I have done the same thing but the value of the text is not updating, please help me
@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?
@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.
@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.
Nope, I just made a compromise as you did. Instead putting the card below the chart. I stacked the card on the chart‘s top-right corner and made it a little transparent.
@joaquinperaza just create simple one variable model, pass it to the
CustomCircleSymbolRenderer
on creation and update inchangedListener
Could you show example code please?
@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.
using gesture detector onTapDown function could help in locating x, y position of tap and you could render the tooltip in more proper location
@stasgora the solution works well and I am more or less getting the desired outcome.
But to achieve it, we need to import files from src folder of the library, which should be avoided as best as possible. And it does throw the following warning: Don't import implementation files from another package.
Any idea how to resolve this, till an official solution is available?
@kamaleshbasu not possible afaik, if it was possible, that would be an official solution of sorts (one that does not involve using internal files)
Thank you!
Excuse me ! how u get the solution? setState will cause anothor question ...
@FannyFanFan you don't use setState() as it will trigger rebuild.
it's kind of a hacked solution where you use a global variable to keep track of the currently selected point. it is definitely an anti-pattern. Till the authors of the plugin enable a feature for us to control/display the labels programmatically, we have to make do with the hacked solution.
I migrated to this library https://github.com/imaNNeoFighT/fl_chart
Hello,
It can be done with Provider package i will post example today.
Basicaly what we need is to provide value to CustomCircleSymbolRenderer and than only this part will rebuild without whole widget
A solution is to create a static String variable inside the "CustomCircleSymbolRenderer" class. Make sure to update this variable in the "changedListener" with the new selected value.
@stasgora @pockyzhang @zarulizham
Thank you @stasgora ! Hey @zarulizham ! No need to use setState((){}); Just create a static variable and access it from CustomMeasureTickCount.
I have just modified the code. See :
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'dart:math';
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 CustomMeasureTickCount extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
static String pointerValue;
CustomMeasureTickCount(this.seriesList, {this.animate});
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory CustomMeasureTickCount.withSampleData() {
return new CustomMeasureTickCount(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
@override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(seriesList,
animate: animate,
behaviors: [
LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer())
],
selectionModels: [
SelectionModelConfig(changedListener: (SelectionModel model) {
if (model.hasDatumSelection)
pointerValue = model.selectedSeries[0]
.measureFn(model.selectedDatum[0].index)
.toString();
})
],
/// Customize the measure axis to have 10 ticks
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec:
new charts.BasicNumericTickProviderSpec(desiredTickCount: 10)));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
new MyRow(new DateTime(2017, 9, 25), 6),
new MyRow(new DateTime(2017, 9, 26), 8),
new MyRow(new DateTime(2017, 9, 27), 6),
new MyRow(new DateTime(2017, 9, 28), 9),
new MyRow(new DateTime(2017, 9, 29), 11),
new MyRow(new DateTime(2017, 9, 30), 15),
new MyRow(new DateTime(2017, 10, 01), 25),
new MyRow(new DateTime(2017, 10, 02), 33),
new MyRow(new DateTime(2017, 10, 03), 27),
new MyRow(new DateTime(2017, 10, 04), 31),
new MyRow(new DateTime(2017, 10, 05), 23),
];
return [
new charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
colorFn: (_, __) => charts.MaterialPalette.indigo.shadeDefault,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int cost;
MyRow(this.timeStamp, this.cost);
}
class CustomCircleSymbolRenderer extends CircleSymbolRenderer {
@override
void paint(ChartCanvas canvas, Rectangle bounds,
{List 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(CustomMeasureTickCount.pointerValue, style: textStyle),
(bounds.left).round(),
(bounds.top - 28).round());
}
}
Hi, did anyone figure out how to show labels on line chart yet without clicking?
@zjelo it's not possible in Flutter on mobile; only on web. This is due to the difference in mouse events on web and touch pointer events on mobile. You can try to emulate it by wrapping the chart in a Listener
class.
To the Charts developers, the solution presented in this ticket works but not with ScatterPlotChart. Is there a way to make it work with ScatterPlotChart with multiple series. Here's my chart:
Widget _buildChart(BuildContext context) {
final num now = DateTime.now().toLocal().millisecondsSinceEpoch * 1.0;
final num start = now - (1000 * 60 * 60 * 24);
return new charts.ScatterPlotChart(_getSeries(),
animate: true,
behaviors: [charts.LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer(() => selection))],
selectionModels: [
charts.SelectionModelConfig(changedListener: (charts.SelectionModel model) {
if (model.hasDatumSelection) {
int date = model.selectedDatum[0].datum.date;
selection = '${this.bpMap[date].systolic}/${this.bpMap[date].diastolic}';
}
})
],
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec: new charts.BasicNumericTickProviderSpec(zeroBound: false),
renderSpec: charts.SmallTickRendererSpec(
minimumPaddingBetweenLabelsPx: 10, axisLineStyle: charts.LineStyleSpec(color: ChartColors.transparent)),
),
domainAxis: new charts.NumericAxisSpec(
viewport: charts.NumericExtents(start, now),
tickProviderSpec: new charts.BasicNumericTickProviderSpec(zeroBound: false, dataIsInWholeNumbers: true),
renderSpec: charts.SmallTickRendererSpec(
labelOffsetFromTickPx: 10,
minimumPaddingBetweenLabelsPx: 10,
axisLineStyle: charts.LineStyleSpec(color: ChartColors.transparent)),
tickFormatterSpec: charts.BasicNumericTickFormatterSpec((measure) {
final DateTime date = DateTime.fromMillisecondsSinceEpoch(measure.toInt());
int hour = date.hour;
return hour < 10 ? '0${hour}00' : '${hour}00';
})),
defaultRenderer: new charts.PointRendererConfig(
pointRendererDecorators: [new charts.ComparisonPointsDecorator(symbolRenderer: new charts.CylinderSymbolRenderer())]));
}
The selection model is firing correctly but the custom symbol renderer is not ever being called. Here's a screenshot of two charts I'm using. The top line chart shows the tooltip correctly on click. The bottom scatter chart does not
@stasgora @AbhijeetBharti On a timeseries chart with multiple lines, when click on a line the label shows in the wrong line,
when touch on the red line, the value shows on the blue, please help
I didn't use google / charts, sorry
------------------ 原始邮件 ------------------ 发件人: "Sarathlal13"<notifications@github.com>; 发送时间: 2020年3月5日(星期四) 晚上8:33 收件人: "google/charts"<charts@noreply.github.com>; 抄送: "叽歪的蚊子"<740551528@qq.com>; "Comment"<comment@noreply.github.com>; 主题: Re: [google/charts] Is it possible to add marker/tooltip on line chart and bar chart? (#58)
when touch on the red line, the value shows on the blue, please help
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.
I also encountered this problem when using linechart. There is no parameter to support tooltip. I referenced the reply from @stasgora , so I implemented a CustomCircleSymbolRenderer and a TooltipMgr class. TooltipMgr is mainly responsible for the problem that CustomCircleSymbolRenderer cannot pass in parameters. CustomCircleSymbolRenderer is mainly rendering. tooltip. Here is the code and approximate screenshot of my implementation:
// tooltip.dart
import 'dart:math';
import 'package:bill/adaptor.dart';
import 'package:charts_flutter/flutter.dart';
import 'package:charts_flutter/src/text_element.dart' as ChartText;
import 'package:charts_flutter/src/text_style.dart' as ChartStyle;
import 'package:flutter/material.dart';
String _title;
String _subTitle;
class ToolTipMgr {
static String get title => _title;
static String get subTitle => _subTitle;
static setTitle(Map<String, dynamic> data) {
if (data['title'] != null && data['title'].length > 0) {
_title = data['title'];
}
if (data['subTitle'] != null && data['subTitle'].length > 0) {
_subTitle = data['subTitle'];
}
}
}
class CustomCircleSymbolRenderer extends CircleSymbolRenderer {
double height = Adaptor.px(450.0);
@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,
strokeColor: strokeColor,
strokeWidthPx: strokeWidthPx);
canvas.drawRect(Rectangle(bounds.left - 5, bounds.top, bounds.width + 100, bounds.height + 10), fill: Color.black);
ChartStyle.TextStyle textStyle = ChartStyle.TextStyle();
textStyle.color = Color.white;
textStyle.fontSize = 15;
canvas.drawText(ChartText.TextElement(ToolTipMgr.title, style: textStyle),
(bounds.left).round(), (bounds.top + 2).round());
}
}
// mypage.dart
// import other modules
import './tooltip.dart';
class SelectionLineHighlight extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SelectionLineHighlight(this.seriesList, {this.animate});
factory SelectionLineHighlight.withSampleData() {
return new SelectionLineHighlight(
_createSampleData(),
animate: false,
);
}
@override
Widget build(BuildContext context) {
// This is just a simple line chart with a behavior that highlights the
// selected points along the lines. A point will be drawn at the selected
// datum's x,y coordinate, and a vertical follow line will be drawn through
// it.
//
// A [Charts.LinePointHighlighter] behavior is added manually to enable the
// highlighting effect.
//
// As an alternative, [defaultInteractions] can be set to true to include
// the default chart interactions, including a LinePointHighlighter.
return new charts.LineChart(
seriesList,
animate: animate,
defaultRenderer: charts.LineRendererConfig(
includeArea: true,
includePoints: false,
includeLine: false,
stacked: true,
),
behaviors: [
new charts.LinePointHighlighter(
symbolRenderer: CustomCircleSymbolRenderer()),
new charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag)
],
selectionModels: [
charts.SelectionModelConfig(
changedListener: (charts.SelectionModel model) {
if (model.hasDatumSelection) {
ToolTipMgr.setTitle({
'title': '${model.selectedSeries[0].measureFn(model.selectedDatum[0].datum.year)}',
'subTitle': '111133'
});
// print(${model.selectedSeries[0].measureFn(model.selectedDatum[0].datum.year)});
}
})
]
);
}
/// 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, 1000),
new LinearSales(3, 75),
new LinearSales(4, 75),
new LinearSales(6, 100)
];
return [
new charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
and you can jump to the TooltipMgr class and the paint method in CustomCircleSymbolRenderer according to the specific business.
@joaquinperaza just create simple one variable model, pass it to the
CustomCircleSymbolRenderer
on creation and update inchangedListener
Could you please show me, how to do that by providing some code snippet? Thanks a lot!
Hi, Using CustomCircleSymbolRenderer works perfectly for bar chart. Can a similar markup be done for pie chart ?
Hello, how to show tooltip on line chart without clicking on it?
when touch on the red line, the value shows on the blue, please help
hey is there any way to focus tooltip on both lines simultaneouly??
means for the same value of x axis how can i show the value of both red and blue graph in label
Hi, I am able to use it on Bar Chart however there is no effect on Pie Chart. Can this be use on Pie Chart?
LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer())
class CustomCircleSymbolRenderer extends CircleSymbolRenderer
I also encountered this problem when using linechart. There is no parameter to support tooltip. I referenced the reply from @stasgora , so I implemented a CustomCircleSymbolRenderer and a TooltipMgr class. TooltipMgr is mainly responsible for the problem that CustomCircleSymbolRenderer cannot pass in parameters. CustomCircleSymbolRenderer is mainly rendering. tooltip. Here is the code and approximate screenshot of my implementation:
// tooltip.dart import 'dart:math'; import 'package:bill/adaptor.dart'; import 'package:charts_flutter/flutter.dart'; import 'package:charts_flutter/src/text_element.dart' as ChartText; import 'package:charts_flutter/src/text_style.dart' as ChartStyle; import 'package:flutter/material.dart'; String _title; String _subTitle; class ToolTipMgr { static String get title => _title; static String get subTitle => _subTitle; static setTitle(Map<String, dynamic> data) { if (data['title'] != null && data['title'].length > 0) { _title = data['title']; } if (data['subTitle'] != null && data['subTitle'].length > 0) { _subTitle = data['subTitle']; } } } class CustomCircleSymbolRenderer extends CircleSymbolRenderer { double height = Adaptor.px(450.0); @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, strokeColor: strokeColor, strokeWidthPx: strokeWidthPx); canvas.drawRect(Rectangle(bounds.left - 5, bounds.top, bounds.width + 100, bounds.height + 10), fill: Color.black); ChartStyle.TextStyle textStyle = ChartStyle.TextStyle(); textStyle.color = Color.white; textStyle.fontSize = 15; canvas.drawText(ChartText.TextElement(ToolTipMgr.title, style: textStyle), (bounds.left).round(), (bounds.top + 2).round()); } }
// mypage.dart // import other modules import './tooltip.dart'; class SelectionLineHighlight extends StatelessWidget { final List<charts.Series> seriesList; final bool animate; SelectionLineHighlight(this.seriesList, {this.animate}); factory SelectionLineHighlight.withSampleData() { return new SelectionLineHighlight( _createSampleData(), animate: false, ); } @override Widget build(BuildContext context) { // This is just a simple line chart with a behavior that highlights the // selected points along the lines. A point will be drawn at the selected // datum's x,y coordinate, and a vertical follow line will be drawn through // it. // // A [Charts.LinePointHighlighter] behavior is added manually to enable the // highlighting effect. // // As an alternative, [defaultInteractions] can be set to true to include // the default chart interactions, including a LinePointHighlighter. return new charts.LineChart( seriesList, animate: animate, defaultRenderer: charts.LineRendererConfig( includeArea: true, includePoints: false, includeLine: false, stacked: true, ), behaviors: [ new charts.LinePointHighlighter( symbolRenderer: CustomCircleSymbolRenderer()), new charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag) ], selectionModels: [ charts.SelectionModelConfig( changedListener: (charts.SelectionModel model) { if (model.hasDatumSelection) { ToolTipMgr.setTitle({ 'title': '${model.selectedSeries[0].measureFn(model.selectedDatum[0].datum.year)}', 'subTitle': '111133' }); // print(${model.selectedSeries[0].measureFn(model.selectedDatum[0].datum.year)}); } }) ] ); } /// 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, 1000), new LinearSales(3, 75), new LinearSales(4, 75), new LinearSales(6, 100) ]; return [ new charts.Series<LinearSales, int>( id: 'Sales', domainFn: (LinearSales sales, _) => sales.year, measureFn: (LinearSales sales, _) => sales.sales, data: data, ) ]; } }
and you can jump to the TooltipMgr class and the paint method in CustomCircleSymbolRenderer according to the specific business.
hey, is it possible to make tooltip title font bold and add some color to it ?
@stasgora @pockyzhang @zarulizham
Thank you @stasgora ! Hey @zarulizham ! No need to use setState((){}); Just create a static variable and access it from CustomMeasureTickCount.
I have just modified the code. See :
import 'package:charts_flutter/flutter.dart' as charts; import 'package:flutter/material.dart'; import 'dart:math'; 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 CustomMeasureTickCount extends StatelessWidget { final List<charts.Series> seriesList; final bool animate; static String pointerValue; CustomMeasureTickCount(this.seriesList, {this.animate}); /// Creates a [TimeSeriesChart] with sample data and no transition. factory CustomMeasureTickCount.withSampleData() { return new CustomMeasureTickCount( _createSampleData(), // Disable animations for image tests. animate: false, ); } @override Widget build(BuildContext context) { return new charts.TimeSeriesChart(seriesList, animate: animate, behaviors: [ LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer()) ], selectionModels: [ SelectionModelConfig(changedListener: (SelectionModel model) { if (model.hasDatumSelection) pointerValue = model.selectedSeries[0] .measureFn(model.selectedDatum[0].index) .toString(); }) ], /// Customize the measure axis to have 10 ticks primaryMeasureAxis: new charts.NumericAxisSpec( tickProviderSpec: new charts.BasicNumericTickProviderSpec(desiredTickCount: 10))); } /// Create one series with sample hard coded data. static List<charts.Series<MyRow, DateTime>> _createSampleData() { final data = [ new MyRow(new DateTime(2017, 9, 25), 6), new MyRow(new DateTime(2017, 9, 26), 8), new MyRow(new DateTime(2017, 9, 27), 6), new MyRow(new DateTime(2017, 9, 28), 9), new MyRow(new DateTime(2017, 9, 29), 11), new MyRow(new DateTime(2017, 9, 30), 15), new MyRow(new DateTime(2017, 10, 01), 25), new MyRow(new DateTime(2017, 10, 02), 33), new MyRow(new DateTime(2017, 10, 03), 27), new MyRow(new DateTime(2017, 10, 04), 31), new MyRow(new DateTime(2017, 10, 05), 23), ]; return [ new charts.Series<MyRow, DateTime>( id: 'Cost', domainFn: (MyRow row, _) => row.timeStamp, measureFn: (MyRow row, _) => row.cost, data: data, colorFn: (_, __) => charts.MaterialPalette.indigo.shadeDefault, ) ]; } } /// Sample time series data type. class MyRow { final DateTime timeStamp; final int cost; MyRow(this.timeStamp, this.cost); } class CustomCircleSymbolRenderer extends CircleSymbolRenderer { @override void paint(ChartCanvas canvas, Rectangle bounds, {List 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(CustomMeasureTickCount.pointerValue, style: textStyle), (bounds.left).round(), (bounds.top - 28).round()); } }
For the Stacked Bar Chart I'm getting same value for all Bar in a single Stack
is it possible show it for a single bar? I'm using following code for generating Stacked Bar chart.
charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.stacked,
behaviors: [
LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer(),
drawFollowLinesAcrossChart: false,
defaultRadiusPx: 5,
showVerticalFollowLine: charts.LinePointHighlighterFollowLineType.none,
selectionModelType: charts.SelectionModelType.info,
showHorizontalFollowLine: charts.LinePointHighlighterFollowLineType.none,
)
],
selectionModels: [
SelectionModelConfig(changedListener: (SelectionModel model) {
if (model.hasDatumSelection)
pointerValue = "Selected: "+model.selectedSeries[0]
.measureFn(model.selectedDatum[0].index)
.toString();
print(pointerValue);
})
],
);
For the Stacked Bar Chart I'm getting same value for all Bar in a single Stack
is it possible show it for a single bar? I'm using following code for generating Stacked Bar chart.
charts.BarChart( seriesList, animate: animate, barGroupingType: charts.BarGroupingType.stacked, behaviors: [ LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer(), drawFollowLinesAcrossChart: false, defaultRadiusPx: 5, showVerticalFollowLine: charts.LinePointHighlighterFollowLineType.none, selectionModelType: charts.SelectionModelType.info, showHorizontalFollowLine: charts.LinePointHighlighterFollowLineType.none, ) ], selectionModels: [ SelectionModelConfig(changedListener: (SelectionModel model) { if (model.hasDatumSelection) pointerValue = "Selected: "+model.selectedSeries[0] .measureFn(model.selectedDatum[0].index) .toString(); print(pointerValue); }) ], );
did you figure out with this problem?
thanks everyone! I did it ❤️
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);
}
}
}
}
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?