From 73c46ea02827312972ab2b0a94c602a6864a5fc8 Mon Sep 17 00:00:00 2001 From: Gayathri-GA Date: Fri, 16 Jun 2023 11:28:54 +0530 Subject: [PATCH 1/4] Added vertical bar chart rendering to bar chart base --- example/lib/main.dart | 48 ++++----- lib/src/bar_chart/bar_chart_axis.dart | 141 ++++++++++++++------------ 2 files changed, 102 insertions(+), 87 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 6bfcf22..7df9069 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -34,9 +34,9 @@ class _MyHomePageState extends State { Widget build(BuildContext context) { return const Scaffold( body: BarChart( - title: BarChartTextTitle( - text: 'Flutter Chart', - textStyle: TextStyle(fontSize: 50, color: Colors.teal)), + // title: BarChartTextTitle( + // text: 'Flutter Chart', + // textStyle: TextStyle(fontSize: 50, color: Colors.teal)), // barChartLegends: BarChartLegends( // legendTextXAxis: "X-Axis", // legendTextYAxis: "Y-Axis", @@ -61,8 +61,8 @@ class _MyHomePageState extends State { // yAxisMainColor: Colors.deepOrangeAccent, // xAxisMainStrokeType: StrokeCap.square, // yAxisMainStrokeType: StrokeCap.butt, - xAxisStartPoint: 0, - xAxisEndPoint: 5.5, + // xAxisStartPoint: 0.0, + // xAxisEndPoint: 10.0, // yAxisStartPoint: 0, // yAxisEndPoint: 100, // xAxisSteps: 90, @@ -71,27 +71,29 @@ class _MyHomePageState extends State { // xAxisLabelOffset: 80, // yAxisRulerOffset: 100, // yAxisLabelOffset: 50, - xAxisGridRulerThickness: 2.0, - // yAxisGridRulerThickness: 1.0, - xAxisGridRulerColor: Colors.purple, + // xAxisGridRulerThickness: 2.0, + // yAxisGridRulerThickness: 1.0, + // xAxisGridRulerColor: Colors.purple, // yAxisGridRulerColor: Colors.orange, // verticalBarColor: Colors.orange, - // yAxisData: [ - // 1.5, - // 0.6, - // 4.8, - // 5.0, - // 2.2, - // 1.8, - // 0.3, - // 4.2, - // 5.2, - // 2.5, - // 3.3, - //1.2 - // ], - // showXAxisGridRuler: false + // showXAxisGridRuler: false, // showYAxisGridRuler: false, + yAxisData: [ + 0.5, + 2.5, + 3.2, + 4.0, + 5.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 2.2, + 1.8, + 1.2, + ], + verticalBarColor: Colors.orange, ), ), ); diff --git a/lib/src/bar_chart/bar_chart_axis.dart b/lib/src/bar_chart/bar_chart_axis.dart index a7acde0..6790dd7 100644 --- a/lib/src/bar_chart/bar_chart_axis.dart +++ b/lib/src/bar_chart/bar_chart_axis.dart @@ -42,7 +42,6 @@ class BarChartAxis extends LeafRenderObjectWidget { /// Creates a [BarChartAxis] widget. /// - /// The [textStyle] parameter specifies the style of the label text. const BarChartAxis({ Key? key, @@ -80,7 +79,11 @@ class BarChartAxis extends LeafRenderObjectWidget { this.showYAxisGridRuler = true, this.yAxisData = const [], this.verticalBarColor = Colors.blue, - }) : super(key: key); + }) : assert(xAxisStartPoint < xAxisEndPoint, + "X-Axis start point should be always lesser than end point"), + assert(yAxisStartPoint < yAxisEndPoint, + "Y-Axis start point should be always lesser than end point"), + super(key: key); @override RenderObject createRenderObject(BuildContext context) { @@ -270,6 +273,7 @@ class RenderBarChartAxis extends RenderBox { double _thicknessOfYAxis = 0; Size sizeOfXAxisLabel = Size.zero; double extendXAxisStart = 0; + double? legendWidth = 0; double get xAxisRulerHeight => renderXAxisRulerHeight; set xAxisRulerHeight(double value) { @@ -527,7 +531,6 @@ class RenderBarChartAxis extends RenderBox { } } - double? legendWidth = 0; @override void paint(PaintingContext context, Offset offset) { final Canvas canvas = context.canvas; @@ -536,13 +539,13 @@ class RenderBarChartAxis extends RenderBox { double yAxisMainLabelOffset = 0; List xAxesLabel = []; List yAxesLabel = []; - calculateLabelValues( - xAxisStartPoint, xAxisEndPoint, graphWidth, xAxisSteps, xAxesLabel); + calculateLabelValues(xAxisStartPoint, xAxisEndPoint, graphWidth, xAxisSteps, + xAxesLabel, "x"); sizeOfXAxisLabel = getLabelSize( textStyle: xAxisLabelTextStyle, value: xAxesLabel.first.text); calculateLabelValues(yAxisStartPoint, yAxisEndPoint, graphHeight * 3, - yAxisSteps, yAxesLabel); + yAxisSteps, yAxesLabel, "y"); final Paint xAxisRulerPaint = Paint() ..color = xAxisRulerColor ..strokeWidth = xAxisRulerThickness @@ -592,13 +595,13 @@ class RenderBarChartAxis extends RenderBox { showYAxisGridRuler); paintXAxisLabels( graphWidth, + graphHeight, xAxesLabel, canvas, yStartLabelSize, xAxisRulerPaint, xAxisMainPaint, xAxisGridRulerPaint, - verticalBarColor, offset, showXAxisGridRuler, yAxesLabel); @@ -606,34 +609,37 @@ class RenderBarChartAxis extends RenderBox { void paintXAxisLabels( double graphWidth, + double graphHeight, List xAxesLabel, Canvas canvas, Size yStartLabelSize, Paint xAxisRulerPaint, Paint xAxisMainPaint, Paint xAxisGridRulerPaint, - Color verticalBarColor, Offset offset, bool showXAxisGridRuler, List yAxesLabel) { var starLabelSize = getLabelSize( textStyle: xAxisLabelTextStyle, value: xAxesLabel.first.value.toString()); - + final barWidth = yAxisData.isNotEmpty + ? ((graphWidth - (yAxisData.length - 1) * (starLabelSize.width / 2)) / + yAxisData.length) + : 0; Offset a = Offset( - _thicknessOfYAxis - (starLabelSize.width / 2) + yAxisRulerOffset, + _thicknessOfYAxis - + (starLabelSize.width / 2) + + yAxisRulerOffset + + (barWidth / 2), size.height - starLabelSize.height - (yStartLabelSize.height / 2)); - Offset b = Offset(graphWidth - starLabelSize.width, + Offset b = Offset(graphWidth - starLabelSize.width - (barWidth / 2), size.height - starLabelSize.height - (yStartLabelSize.height / 2)); - // Setting x-axis based on yaxis data - xAxesLabel.length = - yAxisData.isNotEmpty ? yAxisData.length : xAxesLabel.length; for (int i = 0; i < xAxesLabel.length; i++) { - double x = a.dx * (1 - (i / (xAxesLabel.length))) + - b.dx * (i / (xAxesLabel.length)); - double y = a.dy * (1 - (i / (xAxesLabel.length))) + - b.dy * (i / (xAxesLabel.length)); + double x = a.dx * (1 - (i / (xAxesLabel.length - 1))) + + b.dx * (i / (xAxesLabel.length - 1)); + double y = a.dy * (1 - (i / (xAxesLabel.length - 1))) + + b.dy * (i / (xAxesLabel.length - 1)); final TextSpan span = TextSpan( text: xAxesLabel[i].value.toString(), style: xAxisLabelTextStyle, @@ -643,32 +649,28 @@ class RenderBarChartAxis extends RenderBox { textDirection: TextDirection.ltr, ); tp.layout(); - // To set offset for the labels + + tp.paint(canvas, Offset(x, y)); + if (yAxisData.isNotEmpty) { - final widthOfBar = (x + (b.dx - a.dx) / (xAxesLabel.length)) - - (x + (starLabelSize.width)) + - (starLabelSize.width / 2); - tp.paint(canvas, Offset(x + (widthOfBar / 2), y)); + canvas.drawLine( + Offset(x + starLabelSize.width / 2 + (barWidth / 2), + y - xAxisLabelOffset), + Offset(x + starLabelSize.width / 2 + (barWidth / 2), + (y - xAxisLabelOffset) - xAxisRulerHeight), + xAxisRulerPaint, + ); } else { - tp.paint(canvas, Offset(x, y)); + canvas.drawLine( + Offset(x + starLabelSize.width / 2, y - xAxisLabelOffset), + Offset(x + starLabelSize.width / 2, + (y - xAxisLabelOffset) - xAxisRulerHeight), + xAxisRulerPaint, + ); } - - canvas.drawLine( - Offset(x + starLabelSize.width / 2, y - xAxisLabelOffset), - Offset(x + starLabelSize.width / 2, - (y - xAxisLabelOffset) - xAxisRulerHeight), - xAxisRulerPaint, - ); // To Draw Grid rulers from x-axis if (showXAxisGridRuler) { - final bool hasYAxisData = yAxisData.isNotEmpty; - final double widthOfBar = (x + (b.dx - a.dx) / (xAxesLabel.length)) - - (x + (starLabelSize.width)) + - (starLabelSize.width / 2); - - final double xPosition = hasYAxisData - ? x + (starLabelSize.width) + widthOfBar - : x + (starLabelSize.width / 2); + final double xPosition = x + (starLabelSize.width / 2); final double yPosition = y - ((size.height - (starLabelSize.height) - @@ -677,37 +679,41 @@ class RenderBarChartAxis extends RenderBox { final double yEndPosition = y - xAxisRulerHeight - xAxisRulerOffset; canvas.drawLine( - Offset(xPosition, yPosition), - Offset(xPosition, yEndPosition), + Offset(xPosition + (barWidth / 2), yPosition), + Offset(xPosition + (barWidth / 2), yEndPosition), xAxisGridRulerPaint, ); } - // To Draw Bars + /// To Draw Vertical Bars if (yAxisData.isNotEmpty && i < xAxesLabel.length) { double currentY = yAxisData[i].toDouble(); - double rectLeft = x + (starLabelSize.width); - - double rectTop = (currentY - yAxisStartPoint) * - (offset.dy - - (y - - xAxisRulerHeight - - xAxisRulerOffset - - (yStartLabelSize.height / 2))) / - (yAxisEndPoint - yAxisStartPoint) + - (y - (xAxisRulerHeight) - xAxisRulerOffset); - - double rectRight = x + (b.dx - a.dx) / (xAxesLabel.length); - double rectBottom = y - (xAxisRulerOffset + xAxisRulerHeight); - Rect rect = Rect.fromLTRB(rectLeft, rectTop, rectRight, rectBottom); - canvas.drawRect(rect, Paint()..color = verticalBarColor); + final barHeight = (currentY - yAxisStartPoint) * + (offset.dy - + (y - + xAxisRulerHeight - + xAxisRulerOffset - + (yStartLabelSize.height / 2))) / + (yAxisEndPoint - yAxisStartPoint); + + // Calculate the top-left and bottom-right coordinates of the bar + final barTop = barHeight + (y - (xAxisRulerHeight) - xAxisRulerOffset); + final barBottom = y - (xAxisRulerOffset + xAxisRulerHeight); + + // Calculate the left and right coordinates of the bar + double barLeft = x + (starLabelSize.width) - (barWidth / 2); + double barRight = barLeft + barWidth - (starLabelSize.width); + // Draw the bar rectangle + final Rect barRect = + Rect.fromLTRB(barLeft, barTop, barRight, barBottom); + canvas.drawRect(barRect, Paint()..color = verticalBarColor); } } - // To draw x axis main + canvas.drawLine( - Offset(a.dx + (starLabelSize.width / 2), + Offset(a.dx + (starLabelSize.width / 2) - (barWidth / 2), a.dy - xAxisRulerHeight - xAxisRulerOffset), - Offset(b.dx + (starLabelSize.width / 2), + Offset(b.dx + (starLabelSize.width / 2) + (barWidth / 2), b.dy - xAxisRulerHeight - xAxisRulerOffset), xAxisMainPaint, ); @@ -792,7 +798,7 @@ class RenderBarChartAxis extends RenderBox { } void calculateLabelValues(double getStart, double getEnd, double sizeValue, - double intervalSize, List label) { + double intervalSize, List label, String axisName) { final double count = math.max(sizeValue / intervalSize, 1.0); double interval = (getEnd - getStart) / (sizeValue / intervalSize); final List intervalDivisions = [10, 5, 2, 1]; @@ -806,9 +812,16 @@ class RenderBarChartAxis extends RenderBox { } interval = currentInterval; } - - for (double i = getStart; i <= getEnd; i += interval) { - label.add(AxesLabel(text: i.toString(), value: i)); + if (yAxisData.isNotEmpty && axisName == "x") { + /// TODO: To Map the X Axis Values as pet the yAxisData.length + for (int i = getStart.toInt(); i < yAxisData.length; i++) { + double value = yAxisData[i].toDouble(); + label.add(AxesLabel(text: value.toString(), value: i.toDouble())); + } + } else { + for (double i = getStart; i <= getEnd; i += interval) { + label.add(AxesLabel(text: i.toString(), value: i)); + } } } From f0a76d8446cedfea47273d046238c79213688cb3 Mon Sep 17 00:00:00 2001 From: Gayathri-GA Date: Fri, 16 Jun 2023 11:45:11 +0530 Subject: [PATCH 2/4] Added vertical bar chart rendering to bar chart base --- example/lib/main.dart | 8 ++++---- lib/src/bar_chart/bar_chart_axis.dart | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 7df9069..e73bada 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -61,8 +61,8 @@ class _MyHomePageState extends State { // yAxisMainColor: Colors.deepOrangeAccent, // xAxisMainStrokeType: StrokeCap.square, // yAxisMainStrokeType: StrokeCap.butt, - // xAxisStartPoint: 0.0, - // xAxisEndPoint: 10.0, + // xAxisStartPoint: 0, + // xAxisEndPoint: 5.5, // yAxisStartPoint: 0, // yAxisEndPoint: 100, // xAxisSteps: 90, @@ -72,11 +72,11 @@ class _MyHomePageState extends State { // yAxisRulerOffset: 100, // yAxisLabelOffset: 50, // xAxisGridRulerThickness: 2.0, - // yAxisGridRulerThickness: 1.0, + // yAxisGridRulerThickness: 1.0, // xAxisGridRulerColor: Colors.purple, // yAxisGridRulerColor: Colors.orange, // verticalBarColor: Colors.orange, - // showXAxisGridRuler: false, + // showXAxisGridRuler: false // showYAxisGridRuler: false, yAxisData: [ 0.5, diff --git a/lib/src/bar_chart/bar_chart_axis.dart b/lib/src/bar_chart/bar_chart_axis.dart index 6790dd7..b193833 100644 --- a/lib/src/bar_chart/bar_chart_axis.dart +++ b/lib/src/bar_chart/bar_chart_axis.dart @@ -814,6 +814,7 @@ class RenderBarChartAxis extends RenderBox { } if (yAxisData.isNotEmpty && axisName == "x") { /// TODO: To Map the X Axis Values as pet the yAxisData.length + for (int i = getStart.toInt(); i < yAxisData.length; i++) { double value = yAxisData[i].toDouble(); label.add(AxesLabel(text: value.toString(), value: i.toDouble())); From 82961415edd95e467222109905f7710d46aa9dfa Mon Sep 17 00:00:00 2001 From: Gayathri-GA Date: Mon, 19 Jun 2023 12:28:59 +0530 Subject: [PATCH 3/4] Alignment of vertical bar chart is updated --- lib/src/bar_chart/bar_chart_axis.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/bar_chart/bar_chart_axis.dart b/lib/src/bar_chart/bar_chart_axis.dart index aed00b2..ca156c6 100644 --- a/lib/src/bar_chart/bar_chart_axis.dart +++ b/lib/src/bar_chart/bar_chart_axis.dart @@ -711,8 +711,12 @@ class RenderBarChartAxis extends RenderBox { final barBottom = y - (xAxisRulerOffset + xAxisRulerHeight); // Calculate the left and right coordinates of the bar - double barLeft = x + (starLabelSize.width) - (barWidth / 2); - double barRight = barLeft + barWidth - (starLabelSize.width); + double barLeft = + x + (starLabelSize.width) - (barWidth / 2) + (_thicknessOfYAxis); + double barRight = barLeft + + barWidth - + (starLabelSize.width) - + (_thicknessOfYAxis * 2); // Draw the bar rectangle final Rect barRect = Rect.fromLTRB(barLeft, barTop, barRight, barBottom); From a45d834e8482a8893618b75bd4d3f54850d71e8b Mon Sep 17 00:00:00 2001 From: Gayathri-GA Date: Mon, 19 Jun 2023 13:57:17 +0530 Subject: [PATCH 4/4] Updated calculate label values function for generating labels for x-axis --- example/lib/main.dart | 1 + lib/src/bar_chart/bar_chart_axis.dart | 31 ++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index f2634c2..6e5593a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -63,6 +63,7 @@ class _MyHomePageState extends State { // yAxisMainStrokeType: StrokeCap.butt, // xAxisStartPoint: 0, // xAxisEndPoint: 5.5, + // xAxisIntervalRange: 0.5, // yAxisStartPoint: 0, // yAxisEndPoint: 100, // xAxisSteps: 90, diff --git a/lib/src/bar_chart/bar_chart_axis.dart b/lib/src/bar_chart/bar_chart_axis.dart index ca156c6..c5a6131 100644 --- a/lib/src/bar_chart/bar_chart_axis.dart +++ b/lib/src/bar_chart/bar_chart_axis.dart @@ -25,6 +25,7 @@ class BarChartAxis extends LeafRenderObjectWidget { final Color yAxisGridRulerColor; final double xAxisStartPoint; final double xAxisEndPoint; + final double xAxisIntervalRange; final double yAxisStartPoint; final double yAxisEndPoint; final double xAxisSteps; @@ -63,6 +64,7 @@ class BarChartAxis extends LeafRenderObjectWidget { this.yAxisGridRulerColor = Colors.grey, this.xAxisStartPoint = 0.0, this.xAxisEndPoint = 5.5, + this.xAxisIntervalRange = 0.5, this.yAxisStartPoint = 0.0, this.yAxisEndPoint = 5.5, this.xAxisSteps = 100, @@ -106,6 +108,7 @@ class BarChartAxis extends LeafRenderObjectWidget { yAxisGridRulerColor: yAxisGridRulerColor, xAxisStartPoint: xAxisStartPoint, xAxisEndPoint: xAxisEndPoint, + xAxisIntervalRange: xAxisIntervalRange, yAxisStartPoint: yAxisStartPoint, yAxisEndPoint: yAxisEndPoint, xAxisSteps: xAxisSteps, @@ -145,6 +148,7 @@ class BarChartAxis extends LeafRenderObjectWidget { ..yAxisGridRulerColor = yAxisGridRulerColor ..xAxisStartPoint = xAxisStartPoint ..xAxisEndPoint = xAxisEndPoint + ..xAxisIntervalRange = xAxisIntervalRange ..yAxisStartPoint = yAxisStartPoint ..yAxisEndPoint = yAxisEndPoint ..xAxisSteps = xAxisSteps @@ -194,6 +198,7 @@ class RenderBarChartAxis extends RenderBox { Color renderYAxisGridRulerColor; double renderXAxisStartPoint; double renderXAxisEndPoint; + double renderXAxisIntervalRange; double renderYAxisStartPoint; double renderYAxisEndPoint; double renderXAxisSteps; @@ -224,6 +229,7 @@ class RenderBarChartAxis extends RenderBox { required Color yAxisGridRulerColor, required double xAxisStartPoint, required double xAxisEndPoint, + required double xAxisIntervalRange, required double yAxisStartPoint, required double yAxisEndPoint, required TextStyle xAxisLabelTextStyle, @@ -256,6 +262,7 @@ class RenderBarChartAxis extends RenderBox { renderYAxisGridRulerColor = yAxisGridRulerColor, renderXAxisStartPoint = xAxisStartPoint, renderXAxisEndPoint = xAxisEndPoint, + renderXAxisIntervalRange = xAxisIntervalRange, renderYAxisStartPoint = yAxisStartPoint, renderYAxisEndPoint = yAxisEndPoint, renderXAxisSteps = xAxisSteps, @@ -452,6 +459,14 @@ class RenderBarChartAxis extends RenderBox { } } + double get xAxisIntervalRange => renderXAxisIntervalRange; + set xAxisIntervalRange(double value) { + if (renderXAxisIntervalRange != value) { + renderXAxisIntervalRange = value; + markNeedsLayout(); + } + } + double get yAxisStartPoint => renderYAxisStartPoint; set yAxisStartPoint(double value) { if (renderYAxisStartPoint != value) { @@ -518,6 +533,8 @@ class RenderBarChartAxis extends RenderBox { List get yAxisData => renderYAxisData; set yAxisData(List value) { + assert(value.length <= (xAxisEndPoint - xAxisStartPoint) + 1, + "Y-Axis data length should be always lesser than X-Axis range"); if (renderYAxisData != value) { renderYAxisData = value; markNeedsLayout(); @@ -827,11 +844,15 @@ class RenderBarChartAxis extends RenderBox { interval = currentInterval; } if (yAxisData.isNotEmpty && axisName == "x") { - /// TODO: To Map the X Axis Values as pet the yAxisData.length - - for (int i = getStart.toInt(); i < yAxisData.length; i++) { - double value = yAxisData[i].toDouble(); - label.add(AxesLabel(text: value.toString(), value: i.toDouble())); + int length = yAxisData.length; + List xAxisData = []; + + for (int i = getStart.toInt(); i < length; i++) { + double value = getStart + (i * xAxisIntervalRange); + xAxisData.add(value); + double labelValue = xAxisData[i].toDouble(); + label.add(AxesLabel( + text: labelValue.toString(), value: labelValue.toDouble())); } } else { for (double i = getStart; i <= getEnd; i += interval) {