Open unarayan-sf opened 1 month ago
Hi @unarayan-sf,
You can achieve your requirement for a doughnut chart with rounded corners and gaps by using the _CustomDoughnutSeries. By updating the calculateRoundedCornerArcPath() method in custom doughnut segment, you can adjust the corners at the start and end of each segment. Finally, initialize the custom doughnut series in the chart using the onCreateRenderer callback to render the customized segment. Please refer to the following code snippet.
Custom doughnut series:
class _CustomDoughnutSeries<_ChartData, int>
extends DoughnutSeriesRenderer<_ChartData, int> {
@override
DoughnutSegment<_ChartData, int> createSegment() {
return _ColumnCustomPainter();
}
}
class _ColumnCustomPainter<_ChartData, int>
extends DoughnutSegment<_ChartData, int> {
@override
void onPaint(Canvas canvas) {
final Paint paint = getFillPaint();
final num angleDeviation = findAngleDeviation(
series.currentInnerRadius, series.currentRadius, 360);
fillPath = calculateRoundedCornerArcPath(
series.currentInnerRadius,
series.currentRadius,
series.center,
startAngle + angleDeviation,
endAngle - angleDeviation,
1);
canvas.drawPath(fillPath, paint);
}
}
num findAngleDeviation(num innerRadius, num outerRadius, num totalAngle) {
final num midRadius = (innerRadius + outerRadius) / 2;
final num circumference = 2 * pi * midRadius;
final num rimSize = (innerRadius - outerRadius).abs();
final num deviation = ((rimSize / 2) / circumference) * 100;
return (deviation * 360) / 100;
}
Path calculateRoundedCornerArcPath(double innerRadius, double outerRadius,
Offset center, double startAngle, double endAngle, double gapAngle) {
final Path path = Path();
// Adjust the start and end angles by reducing them by the gap angle
final double adjustedStartAngle = startAngle + gapAngle / 2;
final double adjustedEndAngle = endAngle - gapAngle / 2;
// Calculate the start and end points
final Offset startPoint =
calculateOffset(adjustedStartAngle, innerRadius, center);
Offset endPoint = calculateOffset(adjustedStartAngle, outerRadius, center);
// Move to the starting point
path.moveTo(startPoint.dx, startPoint.dy);
// Create rounded corner arc at the starting point
path.arcToPoint(endPoint,
radius: Radius.circular((innerRadius - outerRadius).abs() / 2));
// Draw the outer arc with adjusted angles to create the gap
path.addArc(
Rect.fromCircle(center: center, radius: outerRadius),
degreesToRadians(adjustedStartAngle),
degreesToRadians(adjustedEndAngle - adjustedStartAngle));
// Calculate the end point for the inner arc
final Offset endPointCurve =
calculateOffset(adjustedEndAngle, innerRadius, center);
// Create rounded corner arc at the end point
path.arcToPoint(endPointCurve,
radius: Radius.circular((innerRadius - outerRadius).abs() / 2));
// Draw the inner arc to close the shape
path.arcTo(
Rect.fromCircle(center: center, radius: innerRadius),
degreesToRadians(adjustedEndAngle),
degreesToRadians(adjustedStartAngle) - degreesToRadians(adjustedEndAngle),
false);
return path;
}
Offset calculateOffset(double degree, double radius, Offset center) {
final double radian = degreesToRadians(degree);
return Offset(
center.dx + cos(radian) * radius, center.dy + sin(radian) * radius);
}
double degreesToRadians(double deg) => deg * (pi / 180);
Set the custom doughnut series to chart:
SfCircularChart(
series: <DoughnutSeries<_ChartData, String>>[
DoughnutSeries<_ChartData, String>(
dataSource: data,
xValueMapper: (_ChartData data, _) => data.category,
yValueMapper: (_ChartData data, _) => data.value,
innerRadius: "80%",
onCreateRenderer: (series) {
return _CustomDoughnutSeries();
}),
],
),
Demo:
We have attached the sample below for you reference. Please check and get back to us if your require further assistance.
Sample : GH_2111.zip
Regards, Baranibharathi P.
Use case
In the doughnut graph, we have a corner style property, setting its value gives a circular arch, we want to make only the corner rounded no arch. (see design). I tried making the CustomDoughnutSeries series and extending the doughnut graph but couldn't accomplish it. I need to know how I can approach this issue. any code sample help is appreciated.
Proposal
can someone give me an idea of how we can do it? Thank you so much Guys.