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 capStyle for Pie Charts #1832

Open
wants to merge 3 commits into
base: main
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
4 changes: 1 addition & 3 deletions example/lib/presentation/samples/pie/pie_chart_sample2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ class PieChart2State extends State {
aspectRatio: 1.3,
child: Row(
children: <Widget>[
const SizedBox(
height: 18,
),
Expanded(
child: AspectRatio(
aspectRatio: 1,
Expand All @@ -41,6 +38,7 @@ class PieChart2State extends State {
});
},
),
capStyle: CapStyle.none,
borderData: FlBorderData(
show: false,
),
Expand Down
6 changes: 3 additions & 3 deletions example/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c
package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404

PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7

COCOAPODS: 1.16.2
COCOAPODS: 1.15.2
21 changes: 20 additions & 1 deletion lib/src/chart/pie_chart/pie_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ class PieChartData extends BaseChartData with EquatableMixin {
PieTouchData? pieTouchData,
FlBorderData? borderData,
bool? titleSunbeamLayout,
}) : sections = sections ?? const [],
CapStyle? capStyle,
}) : assert(
capStyle == null || centerSpaceRadius != null,
'centerSpaceRadius must not be null if capStyle is provided',
),
sections = sections ?? const [],
centerSpaceRadius = centerSpaceRadius ?? double.infinity,
centerSpaceColor = centerSpaceColor ?? Colors.transparent,
sectionsSpace = sectionsSpace ?? 2,
startDegreeOffset = startDegreeOffset ?? 0,
pieTouchData = pieTouchData ?? PieTouchData(),
titleSunbeamLayout = titleSunbeamLayout ?? false,
capStyle = capStyle ?? CapStyle.none,
super(
borderData: borderData ?? FlBorderData(show: false),
touchData: pieTouchData ?? PieTouchData(),
Expand Down Expand Up @@ -67,6 +73,9 @@ class PieChartData extends BaseChartData with EquatableMixin {
/// Whether to rotate the titles on each section of the chart
final bool titleSunbeamLayout;

/// Cap style of pie charts
final CapStyle capStyle;

/// We hold this value to determine weight of each [PieChartSectionData.value].
double get sumValue => sections
.map((data) => data.value)
Expand All @@ -83,6 +92,7 @@ class PieChartData extends BaseChartData with EquatableMixin {
PieTouchData? pieTouchData,
FlBorderData? borderData,
bool? titleSunbeamLayout,
CapStyle? capStyle,
}) =>
PieChartData(
sections: sections ?? this.sections,
Expand All @@ -93,6 +103,7 @@ class PieChartData extends BaseChartData with EquatableMixin {
pieTouchData: pieTouchData ?? this.pieTouchData,
borderData: borderData ?? this.borderData,
titleSunbeamLayout: titleSunbeamLayout ?? this.titleSunbeamLayout,
capStyle: capStyle ?? this.capStyle,
);

/// Lerps a [BaseChartData] based on [t] value, check [Tween.lerp].
Expand All @@ -107,6 +118,7 @@ class PieChartData extends BaseChartData with EquatableMixin {
b.centerSpaceRadius,
t,
),
capStyle: capStyle,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be capStyle: b.capStyle,

pieTouchData: b.pieTouchData,
sectionsSpace: lerpDouble(a.sectionsSpace, b.sectionsSpace, t),
startDegreeOffset:
Expand All @@ -130,6 +142,7 @@ class PieChartData extends BaseChartData with EquatableMixin {
startDegreeOffset,
borderData,
titleSunbeamLayout,
capStyle,
];
}

Expand Down Expand Up @@ -401,3 +414,9 @@ class PieChartDataTween extends Tween<PieChartData> {
@override
PieChartData lerp(double t) => begin!.lerp(begin!, end!, t);
}

enum CapStyle {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please write a documentation above it. And it seems it is specially for PieChart. So I think it makes sense to add Pie prefix for it.

none,
startCapped,
endCapped,
}
100 changes: 72 additions & 28 deletions lib/src/chart/pie_chart/pie_chart_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
sectionDegree,
center,
centerRadius,
data.capStyle,
);

drawSection(section, sectionPath, canvasWrapper);
Expand All @@ -189,6 +190,7 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
double sectionDegree,
Offset center,
double centerRadius,
CapStyle capStyle,
) {
final sectionRadiusRect = Rect.fromCircle(
center: center,
Expand All @@ -204,32 +206,74 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
final sweepRadians = Utils().radians(sectionDegree);
final endRadians = startRadians + sweepRadians;

final startLineDirection =
Offset(math.cos(startRadians), math.sin(startRadians));
final startLineDirection = Offset(
math.cos(startRadians),
math.sin(startRadians),
);

final startLineFrom = center + startLineDirection * centerRadius;
final startLineTo = startLineFrom + startLineDirection * section.radius;
// sectionRadiusRect.shortestSide; //extra center is added here
final startLine = Line(startLineFrom, startLineTo);

final endLineDirection = Offset(math.cos(endRadians), math.sin(endRadians));
final endLineDirection = Offset(
math.cos(endRadians),
math.sin(endRadians),
);

final endLineFrom = center + endLineDirection * centerRadius;
final endLineTo = endLineFrom + endLineDirection * section.radius;
final endLineTo =
endLineFrom + endLineDirection * section.radius; // extra center
final endLine = Line(endLineFrom, endLineTo);

var sectionPath = Path()
..moveTo(startLine.from.dx, startLine.from.dy)
..lineTo(startLine.to.dx, startLine.to.dy)
..arcTo(sectionRadiusRect, startRadians, sweepRadians, false)
..lineTo(endLine.from.dx, endLine.from.dy)
..arcTo(centerRadiusRect, endRadians, -sweepRadians, false)
..moveTo(startLine.from.dx, startLine.from.dy)
..close();
var sectionPath = Path();
switch (capStyle) {
case CapStyle.startCapped:
sectionPath
..moveTo(startLine.from.dx, startLine.from.dy)
..arcToPoint(
startLine.to,
radius: Radius.circular(section.radius / 2),
)
..arcTo(sectionRadiusRect, startRadians, sweepRadians, false)
..arcToPoint(
endLine.from,
radius: Radius.circular(section.radius / 2),
clockwise: false,
)
..arcTo(centerRadiusRect, endRadians, -sweepRadians, false)
..moveTo(startLine.from.dx, startLine.from.dy)
..close();
case CapStyle.endCapped:
sectionPath
..moveTo(startLine.from.dx, startLine.from.dy)
..arcToPoint(
startLine.to,
radius: Radius.circular(section.radius / 2),
clockwise: false,
)
..arcTo(sectionRadiusRect, startRadians, sweepRadians, false)
..arcToPoint(
endLine.from,
radius: Radius.circular(section.radius / 2),
)
..arcTo(centerRadiusRect, endRadians, -sweepRadians, false)
..moveTo(startLine.from.dx, startLine.from.dy)
..close();
case CapStyle.none:
sectionPath
..moveTo(startLine.from.dx, startLine.from.dy)
..lineTo(startLine.to.dx, startLine.to.dy)
..arcTo(sectionRadiusRect, startRadians, sweepRadians, false)
..lineTo(endLine.from.dx, endLine.from.dy)
..arcTo(centerRadiusRect, endRadians, -sweepRadians, false)
..moveTo(startLine.from.dx, startLine.from.dy)
..close();
}

/// Subtract section space from the sectionPath
if (sectionSpace != 0) {
final startLineSeparatorPath = createRectPathAroundLine(
Line(startLineFrom, startLineTo),
startLine,
sectionSpace,
);
try {
Expand All @@ -238,25 +282,24 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
sectionPath,
startLineSeparatorPath,
);
} catch (_) {
/// It's a flutter engine issue with [Path.combine] in web-html renderer
/// https://github.com/imaNNeo/fl_chart/issues/955
}

final endLineSeparatorPath =
createRectPathAroundLine(Line(endLineFrom, endLineTo), sectionSpace);
try {
sectionPath = Path.combine(
PathOperation.difference,
sectionPath,
endLineSeparatorPath,
);
} catch (_) {
} catch (e) {
/// It's a flutter engine issue with [Path.combine] in web-html renderer
/// https://github.com/imaNNeo/fl_chart/issues/955
}
}

final endLineSeparatorPath =
createRectPathAroundLine(endLine, sectionSpace);
try {
sectionPath = Path.combine(
PathOperation.difference,
sectionPath,
endLineSeparatorPath,
);
} catch (e) {
/// It's a flutter engine issue with [Path.combine] in web-html renderer
/// https://github.com/imaNNeo/fl_chart/issues/955
}
return sectionPath;
}

Expand Down Expand Up @@ -486,6 +529,7 @@ class PieChartPainter extends BaseChartPainter<PieChartData> {
sectionAngle,
center,
centerRadius,
data.capStyle,
);

if (sectionPath.contains(localPosition)) {
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 @@ -28,6 +28,7 @@ When you change the chart's state, it animates to the new state internally (usin
|pieTouchData| [PieTouchData](#pietouchdata-read-about-touch-handling) holds the touch interactivity details| PieTouchData()|
|borderData| shows a border around the chart, check the [FlBorderData](base_chart.md#FlBorderData)|FlBorderData()|
|titleSunbeamLayout| whether to rotate the titles on each section of the chart|false|
|capStyle| whether add cap at the end of pie charts. Only available on pie charts with non-null & non-zero centerSpaceRadius|CapStyle.none|


### PieChartSectionData
Expand Down