Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add border for chart arcs #68

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 34 additions & 31 deletions lib/src/chart_painter.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';

import '../pie_chart.dart';

class PieChartPainter extends CustomPainter {
List<Paint> _paintList = [];
final List<Paint> _paintList = [];
late List<double> _subParts;
List<String>? _subTitles;
double _total = 0;
double _totalAngle = math.pi * 2;
final double _totalAngle = math.pi * 2;

final TextStyle? chartValueStyle;
final Color? chartValueBackgroundColor;
Expand All @@ -23,6 +24,7 @@ class PieChartPainter extends CustomPainter {
final Function? formatChartValues;
final double? strokeWidth;
final Color? emptyColor;
final double border;

double _prevAngle = 0;

Expand All @@ -44,13 +46,15 @@ class PieChartPainter extends CustomPainter {
this.formatChartValues,
this.strokeWidth,
this.emptyColor,
this.border = .05,
}) {
_total = values.fold(0, (v1, v2) => v1 + v2);
for (int i = 0; i < values.length; i++) {
for (var i = 0; i < values.length; i++) {
final paint = Paint()..color = getColor(colorList, i);
if (chartType == ChartType.ring) {
paint.style = PaintingStyle.stroke;
paint.strokeWidth = strokeWidth!;
paint
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth!;
}
_paintList.add(paint);
}
Expand All @@ -64,48 +68,48 @@ class PieChartPainter extends CustomPainter {
if (_total == 0) {
final paint = Paint()..color = emptyColor!;
if (chartType == ChartType.ring) {
paint.style = PaintingStyle.stroke;
paint.strokeWidth = strokeWidth!;
paint
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth!;
}
canvas.drawArc(
new Rect.fromLTWH(0.0, 0.0, side, size.height),
Rect.fromLTWH(0, 0, side, size.height),
_prevAngle,
360,
chartType == ChartType.disc ? true : false,
chartType == ChartType.disc,
paint,
);
} else {
_prevAngle = this.initialAngle! * math.pi / 180;
for (int i = 0; i < _subParts.length; i++) {
_prevAngle = initialAngle! * math.pi / 180;
final gap = _subParts.isNotEmpty ? border : 0;
for (var i = 0; i < _subParts.length; i++) {
canvas.drawArc(
new Rect.fromLTWH(0.0, 0.0, side, size.height),
Rect.fromLTWH(0, 0, side, size.height),
_prevAngle,
(((_totalAngle) / _total) * _subParts[i]),
chartType == ChartType.disc ? true : false,
((_totalAngle / _total) * _subParts[i]) - gap,
chartType == ChartType.disc,
_paintList[i],
);
final radius = showChartValuesOutside ? (side / 2) + 16 : side / 3;
final x = (radius) *
final x = radius *
math.cos(
_prevAngle + ((((_totalAngle) / _total) * _subParts[i]) / 2));
final y = (radius) *
_prevAngle + (((_totalAngle / _total) * _subParts[i]) / 2));
final y = radius *
math.sin(
_prevAngle + ((((_totalAngle) / _total) * _subParts[i]) / 2));
_prevAngle + (((_totalAngle / _total) * _subParts[i]) / 2));
if (_subParts.elementAt(i).toInt() != 0) {
final value = formatChartValues != null
? formatChartValues!(_subParts.elementAt(i))
: _subParts.elementAt(i).toStringAsFixed(this.decimalPlaces!);
: _subParts.elementAt(i).toStringAsFixed(decimalPlaces!);

if (showChartValues) {
final name = showValuesInPercentage!
? (((_subParts.elementAt(i) / _total) * 100)
.toStringAsFixed(this.decimalPlaces!) +
'%')
? ('${((_subParts.elementAt(i) / _total) * 100).toStringAsFixed(decimalPlaces!)}%')
: value;
_drawName(canvas, name, x, y, side);
}
}
_prevAngle = _prevAngle + (((_totalAngle) / _total) * _subParts[i]);
_prevAngle = _prevAngle + ((_totalAngle / _total) * _subParts[i]);
}
}

Expand All @@ -119,25 +123,24 @@ class PieChartPainter extends CustomPainter {
}

void _drawName(Canvas canvas, String? name, double x, double y, double side) {
TextSpan span = TextSpan(
final span = TextSpan(
style: chartValueStyle,
text: name,
);
TextPainter tp = TextPainter(
final tp = TextPainter(
text: span,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
);
tp.layout();
)..layout();

if (showChartValueLabel!) {
//Draw text background box
final rect = Rect.fromCenter(
center: Offset((side / 2 + x), (side / 2 + y)),
center: Offset(side / 2 + x, side / 2 + y),
width: tp.width + 6,
height: tp.height + 4,
);
final rRect = RRect.fromRectAndRadius(rect, Radius.circular(4));
final rRect = RRect.fromRectAndRadius(rect, const Radius.circular(4));
final paint = Paint()
..color = chartValueBackgroundColor ?? Colors.grey[200]!
..style = PaintingStyle.fill;
Expand All @@ -146,7 +149,7 @@ class PieChartPainter extends CustomPainter {
//Finally paint the text above box
tp.paint(
canvas,
new Offset(
Offset(
(side / 2 + x) - (tp.width / 2),
(side / 2 + y) - (tp.height / 2),
),
Expand Down
16 changes: 11 additions & 5 deletions lib/src/legend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ class Legend extends StatelessWidget {
required this.color,
required this.style,
required this.legendShape,
required this.titleRowWidth,
this.legendHeight = 8,
this.legendWidth = 8,
});

final String title;
final Color color;
final TextStyle style;
final BoxShape legendShape;
final double titleRowWidth;
final double legendHeight;
final double legendWidth;

@override
Widget build(BuildContext context) {
Expand All @@ -21,8 +27,8 @@ class Legend extends StatelessWidget {
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(vertical: 2.0),
height: 20.0,
width: 18.0,
height: legendHeight,
width: legendWidth,
decoration: BoxDecoration(
shape: legendShape,
color: color,
Expand All @@ -31,12 +37,12 @@ class Legend extends StatelessWidget {
SizedBox(
width: 8.0,
),
Flexible(
fit: FlexFit.loose,
SizedBox(
width: titleRowWidth,
child: Text(
title,
style: style,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(
Expand Down
4 changes: 4 additions & 0 deletions lib/src/legend_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ class LegendOptions {
final TextStyle legendTextStyle;
final BoxShape legendShape;
final LegendPosition legendPosition;
final double width;
final double height;

const LegendOptions({
this.showLegends = true,
this.showLegendsInRow = false,
this.legendTextStyle = defaultLegendStyle,
this.legendShape = BoxShape.circle,
this.legendPosition = LegendPosition.right,
this.width = 18,
this.height = 20,
});
}
90 changes: 50 additions & 40 deletions lib/src/pie_chart.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
import 'package:pie_chart/src/chart_values_options.dart';

import '../pie_chart.dart';
import 'chart_painter.dart';
import 'chart_values_options.dart';
import 'legend.dart';
import 'utils.dart';

Expand All @@ -11,7 +11,7 @@ enum LegendPosition { top, bottom, left, right }
enum ChartType { disc, ring }

class PieChart extends StatefulWidget {
PieChart({
const PieChart({
required this.dataMap,
this.chartType = ChartType.disc,
this.chartRadius,
Expand All @@ -25,9 +25,11 @@ class PieChart extends StatefulWidget {
this.legendOptions = const LegendOptions(),
this.chartValuesOptions = const ChartValuesOptions(),
this.emptyColor = Colors.grey,
this.border = .05,
Key? key,
}) : super(key: key);

final double border;
final Map<String, double> dataMap;
final ChartType chartType;
final double? chartRadius;
Expand All @@ -50,23 +52,23 @@ class _PieChartState extends State<PieChart>
with SingleTickerProviderStateMixin {
late Animation<double> animation;
AnimationController? controller;
double _animFraction = 0.0;
double _animFraction = 0;

List<String>? legendTitles;
late List<double> legendValues;

void initLegends() {
this.legendTitles = widget.dataMap.keys.toList(growable: false);
legendTitles = widget.dataMap.keys.toList(growable: false);
}

void initValues() {
this.legendValues = widget.dataMap.values.toList(growable: false);
legendValues = widget.dataMap.values.toList(growable: false);
}

void initData() {
assert(
widget.dataMap != null && widget.dataMap.isNotEmpty,
"dataMap passed to pie chart cant be null or empty",
widget.dataMap.isNotEmpty,
'dataMap passed to pie chart cant be null or empty',
);
initLegends();
initValues();
Expand All @@ -77,7 +79,7 @@ class _PieChartState extends State<PieChart>
super.initState();
initData();
controller = AnimationController(
duration: widget.animationDuration ?? Duration(milliseconds: 800),
duration: widget.animationDuration ?? const Duration(milliseconds: 800),
vsync: this,
);
final Animation curve = CurvedAnimation(
Expand All @@ -97,7 +99,7 @@ class _PieChartState extends State<PieChart>
Widget _getChart() {
return Flexible(
child: LayoutBuilder(
builder: (_, c) => Container(
builder: (_, c) => SizedBox(
height: widget.chartRadius != null
? c.maxWidth < widget.chartRadius!
? c.maxWidth
Expand Down Expand Up @@ -125,8 +127,9 @@ class _PieChartState extends State<PieChart>
formatChartValues: widget.formatChartValues,
strokeWidth: widget.ringStrokeWidth,
emptyColor: widget.emptyColor,
border: widget.border,
),
child: AspectRatio(aspectRatio: 1),
child: const AspectRatio(aspectRatio: 1),
),
),
),
Expand Down Expand Up @@ -162,7 +165,8 @@ class _PieChartState extends State<PieChart>
);
case LegendPosition.left:
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_getLegend(
padding: EdgeInsets.only(
Expand Down Expand Up @@ -199,43 +203,49 @@ class _PieChartState extends State<PieChart>
}
}

_getLegend({EdgeInsets? padding}) {
Widget _getLegend({EdgeInsets? padding}) {
if (widget.legendOptions.showLegends) {
return Padding(
padding: padding!,
child: Wrap(
direction: widget.legendOptions.showLegendsInRow
? Axis.horizontal
: Axis.vertical,
runSpacing: 8,
crossAxisAlignment: WrapCrossAlignment.start,
children: legendTitles!
.map(
(item) => Legend(
title: item,
color: getColor(
widget.colorList,
legendTitles!.indexOf(item),
),
style: widget.legendOptions.legendTextStyle,
legendShape: widget.legendOptions.legendShape,
),
)
.toList(),
return Flexible(
child: LayoutBuilder(
builder: (_, c) {
return Padding(
padding: padding!,
child: Wrap(
direction: widget.legendOptions.showLegendsInRow
? Axis.horizontal
: Axis.vertical,
runSpacing: 8,
children: legendTitles!
.map(
(item) => Legend(
title: item,
legendHeight: widget.legendOptions.height,
legendWidth: widget.legendOptions.width,
titleRowWidth: c.maxWidth,
color: getColor(
widget.colorList,
legendTitles!.indexOf(item),
),
style: widget.legendOptions.legendTextStyle,
legendShape: widget.legendOptions.legendShape,
),
)
.toList(),
),
);
},
),
);
} else
return SizedBox(
height: 0,
width: 0,
);
} else {
return const SizedBox();
}
}

@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: _getPieChart(),
);
}
Expand Down