Skip to content

Commit

Permalink
Merge pull request #722 from imaNNeoFighT/feature/pie-chart-stroke
Browse files Browse the repository at this point in the history
Feature/pie chart stroke
  • Loading branch information
imaNNeo authored Jul 22, 2021
2 parents b70b4f9 + 682aa89 commit efaa0ad
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## newVersion
* **IMPROVEMENT** Show proper error message when there is less than 3 [RadarEntry](https://github.com/imaNNeoFighT/fl_chart/blob/master/repo_files/documentations/radar_chart.md#radarentry) in [RadarChart](https://github.com/imaNNeoFighT/fl_chart/blob/master/repo_files/documentations/radar_chart.md), #694.
* **IMPROVEMENT** Added `borderSide` property in [PieChartSectionData](https://github.com/imaNNeoFighT/fl_chart/blob/master/repo_files/documentations/pie_chart.md#piechartsectiondata) to draw strokes around each section, #606.

## 0.36.2
* **IMPROVEMENT** Support `onMouseExit` event in all charts.
Expand Down
27 changes: 23 additions & 4 deletions example/lib/pie_chart/samples/pie_chart_sample1.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'indicator.dart';
import 'package:example/utils/color_extensions.dart';

class PieChartSample1 extends StatefulWidget {
@override
Expand Down Expand Up @@ -97,46 +98,64 @@ class PieChartSample1State extends State {
(i) {
final isTouched = i == touchedIndex;
final opacity = isTouched ? 1.0 : 0.6;

final color0 = const Color(0xff0293ee);
final color1 = const Color(0xfff8b250);
final color2 = const Color(0xff845bef);
final color3 = const Color(0xff13d38e);

switch (i) {
case 0:
return PieChartSectionData(
color: const Color(0xff0293ee).withOpacity(opacity),
color: color0.withOpacity(opacity),
value: 25,
title: '',
radius: 80,
titleStyle: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: const Color(0xff044d7c)),
titlePositionPercentageOffset: 0.55,
borderSide: isTouched
? BorderSide(color: color0.darken(40), width: 6)
: BorderSide(color: color0.withOpacity(0)),
);
case 1:
return PieChartSectionData(
color: const Color(0xfff8b250).withOpacity(opacity),
color: color1.withOpacity(opacity),
value: 25,
title: '',
radius: 65,
titleStyle: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: const Color(0xff90672d)),
titlePositionPercentageOffset: 0.55,
borderSide: isTouched
? BorderSide(color: color1.darken(40), width: 6)
: BorderSide(color: color2.withOpacity(0)),
);
case 2:
return PieChartSectionData(
color: const Color(0xff845bef).withOpacity(opacity),
color: color2.withOpacity(opacity),
value: 25,
title: '',
radius: 60,
titleStyle: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: const Color(0xff4c3788)),
titlePositionPercentageOffset: 0.6,
borderSide: isTouched
? BorderSide(color: color2.darken(40), width: 6)
: BorderSide(color: color2.withOpacity(0)),
);
case 3:
return PieChartSectionData(
color: const Color(0xff13d38e).withOpacity(opacity),
color: color3.withOpacity(opacity),
value: 25,
title: '',
radius: 70,
titleStyle: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: const Color(0xff0c7f55)),
titlePositionPercentageOffset: 0.55,
borderSide: isTouched
? BorderSide(color: color3.darken(40), width: 6)
: BorderSide(color: color2.withOpacity(0)),
);
default:
throw Error();
Expand Down
11 changes: 11 additions & 0 deletions example/lib/utils/color_extensions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';

extension ColorExtension on Color {
/// Convert the color to a darken color based on the [percent]
Color darken([int percent = 40]) {
assert(1 <= percent && percent <= 100);
final value = 1 - percent / 100;
return Color.fromARGB(
alpha, (red * value).round(), (green * value).round(), (blue * value).round());
}
}
8 changes: 8 additions & 0 deletions lib/src/chart/pie_chart/pie_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class PieChartSectionData {
/// Defines text of showing title at the middle of section.
final String title;

/// Defines border stroke around the section
final BorderSide borderSide;

/// Defines a widget that represents the section.
///
/// This can be anything from a text, an image, an animation, and even a combination of widgets.
Expand Down Expand Up @@ -188,6 +191,7 @@ class PieChartSectionData {
bool? showTitle,
TextStyle? titleStyle,
String? title,
BorderSide? borderSide,
Widget? badgeWidget,
double? titlePositionPercentageOffset,
double? badgePositionPercentageOffset,
Expand All @@ -198,6 +202,7 @@ class PieChartSectionData {
titleStyle = titleStyle ??
const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
title = title ?? value.toString(),
borderSide = borderSide ?? BorderSide(width: 0),
badgeWidget = badgeWidget ?? Container(),
titlePositionPercentageOffset = titlePositionPercentageOffset ?? 0.5,
badgePositionPercentageOffset = badgePositionPercentageOffset ?? 0.5;
Expand All @@ -211,6 +216,7 @@ class PieChartSectionData {
bool? showTitle,
TextStyle? titleStyle,
String? title,
BorderSide? borderSide,
Widget? badgeWidget,
double? titlePositionPercentageOffset,
double? badgePositionPercentageOffset,
Expand All @@ -222,6 +228,7 @@ class PieChartSectionData {
showTitle: showTitle ?? this.showTitle,
titleStyle: titleStyle ?? this.titleStyle,
title: title ?? this.title,
borderSide: borderSide ?? this.borderSide,
badgeWidget: badgeWidget ?? this.badgeWidget,
titlePositionPercentageOffset:
titlePositionPercentageOffset ?? this.titlePositionPercentageOffset,
Expand All @@ -239,6 +246,7 @@ class PieChartSectionData {
showTitle: b.showTitle,
titleStyle: TextStyle.lerp(a.titleStyle, b.titleStyle, t),
title: b.title,
borderSide: BorderSide.lerp(a.borderSide, b.borderSide, t),
badgeWidget: b.badgeWidget,
titlePositionPercentageOffset:
lerpDouble(a.titlePositionPercentageOffset, b.titlePositionPercentageOffset, t),
Expand Down
17 changes: 16 additions & 1 deletion lib/src/chart/pie_chart/pie_chart_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'pie_chart_data.dart';

/// Paints [PieChartData] in the canvas, it can be used in a [CustomPainter]
class PieChartPainter extends BaseChartPainter<PieChartData> {
late Paint _sectionPaint, _sectionsSpaceClearPaint, _centerSpacePaint;
late Paint _sectionPaint, _sectionStrokePaint, _sectionsSpaceClearPaint, _centerSpacePaint;

/// Paints [data] into canvas, it is the animating [PieChartData],
/// [targetData] is the animation's target and remains the same
Expand All @@ -25,6 +25,8 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
PieChartPainter() : super() {
_sectionPaint = Paint()..style = PaintingStyle.stroke;

_sectionStrokePaint = Paint()..style = PaintingStyle.stroke;

_sectionsSpaceClearPaint = Paint()
..style = PaintingStyle.fill
..color = const Color(0x000000000)
Expand Down Expand Up @@ -130,6 +132,19 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
_sectionPaint.color = section.color;
_sectionPaint.style = PaintingStyle.fill;
canvasWrapper.drawPath(sectionPath, _sectionPaint);

if (section.borderSide.width != 0.0 && section.borderSide.color.opacity != 0.0) {
canvasWrapper.saveLayer(Rect.fromLTWH(0, 0, viewSize.width, viewSize.height), Paint());
canvasWrapper.clipPath(sectionPath);

_sectionStrokePaint.strokeWidth = section.borderSide.width * 2;
_sectionStrokePaint.color = section.borderSide.color;
canvasWrapper.drawPath(
sectionPath,
_sectionStrokePaint,
);
canvasWrapper.restore();
}
tempAngle += sectionDegree;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/src/utils/canvas_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class CanvasWrapper {
/// Directly calls [Canvas.drawImage]
void drawImage(Image image, Offset offset, Paint paint) => canvas.drawImage(image, offset, paint);

/// Directly calls [Canvas.clipPath]
void clipPath(Path path, {bool doAntiAlias = true}) =>
canvas.clipPath(path, doAntiAlias: doAntiAlias);

/// Directly calls [Canvas.drawRect]
void drawRect(Rect rect, Paint paint) => canvas.drawRect(rect, paint);

Expand Down
1 change: 1 addition & 0 deletions repo_files/documentations/pie_chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ When you change the chart's state, it animates to the new state internally (usin
|showTitle| determines to show or hide the titles on each section|true|
|titleStyle| TextStyle of the titles| TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold)|
|title| title of the section| value|
|borderSide| Defines border stroke around the section | BorderSide(width: 0)|
|badgeWidget| badge component of the section| null|
|titlePositionPercentageOffset|the place of the title in the section, this field should be between 0 and 1|0.5|
|badgePositionPercentageOffset|the place of the badge component in the section, this field should be between 0 and 1|0.5|
Expand Down
Binary file modified repo_files/images/pie_chart/pie_chart_sample_1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions test/chart/radar_chart/radar_chart_data_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,16 @@ void main() {
expect(radarDataSet1 == radarDataSet2, false);

expect(
radarDataSet1 == radarDataSet1Clone.copyWith(dataEntries: [RadarEntry(value: 5)]), false);

expect(radarDataSet1 == radarDataSet1Clone.copyWith(dataEntries: []), false);
radarDataSet1 ==
radarDataSet1Clone.copyWith(
dataEntries: [
RadarEntry(value: 5),
RadarEntry(value: 5),
RadarEntry(value: 5),
],
),
false,
);

expect(radarDataSet1 == radarDataSet1Clone.copyWith(fillColor: Colors.grey), true);

Expand Down

0 comments on commit efaa0ad

Please sign in to comment.