I'm printing custom donut chart bar. And I can't add a border to each element
class DonutChartPainter extends CustomPainter {
final double planCalories;
final double leftCalories;
final double thickness = 40;
DonutChartPainter(this.planCalories, this.leftCalories);
@override
void paint(Canvas canvas, Size size) {
final Paint fillPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = thickness
..strokeCap = StrokeCap.butt;
final Paint borderPaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 1;
final double radius = size.width / 2;
final Offset center = Offset(size.width / 2, size.height / 2);
final double usedCalories = planCalories - leftCalories;
final double leftAngle = (leftCalories / planCalories) * 2 * pi;
final double usedAngle = (usedCalories / planCalories) * 2 * pi;
final double separationOffset = 10;
final Offset usedCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle / 2));
final Offset leftCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle + leftAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle + leftAngle / 2));
Rect usedOvalRect = Rect.fromCircle(center: usedCenter, radius: radius - thickness / 2);
Rect leftOvalRect = Rect.fromCircle(center: leftCenter, radius: radius - thickness / 2);
fillPaint.color = green;
canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, fillPaint);
fillPaint.color = lightGreen;
canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, fillPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
how it looks like^ my chart
when I add this code in the end
canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, borderPaint);
canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, borderPaint);
it looks like this 2
but I need the border I need to add separate black border to each element on the bar to make them more contrast
I'm printing custom donut chart bar. And I can't add a border to each element
class DonutChartPainter extends CustomPainter {
final double planCalories;
final double leftCalories;
final double thickness = 40;
DonutChartPainter(this.planCalories, this.leftCalories);
@override
void paint(Canvas canvas, Size size) {
final Paint fillPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = thickness
..strokeCap = StrokeCap.butt;
final Paint borderPaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 1;
final double radius = size.width / 2;
final Offset center = Offset(size.width / 2, size.height / 2);
final double usedCalories = planCalories - leftCalories;
final double leftAngle = (leftCalories / planCalories) * 2 * pi;
final double usedAngle = (usedCalories / planCalories) * 2 * pi;
final double separationOffset = 10;
final Offset usedCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle / 2));
final Offset leftCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle + leftAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle + leftAngle / 2));
Rect usedOvalRect = Rect.fromCircle(center: usedCenter, radius: radius - thickness / 2);
Rect leftOvalRect = Rect.fromCircle(center: leftCenter, radius: radius - thickness / 2);
fillPaint.color = green;
canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, fillPaint);
fillPaint.color = lightGreen;
canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, fillPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
how it looks like^ my chart
when I add this code in the end
canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, borderPaint);
canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, borderPaint);
it looks like this 2
but I need the border I need to add separate black border to each element on the bar to make them more contrast
Share Improve this question edited Feb 18 at 8:29 Kushnirenko asked Feb 17 at 12:49 KushnirenkoKushnirenko 54 bronze badges2 Answers
Reset to default 0Set strokeCap = StrokeCap.round
when creating the paint
object.
example:
class CustomPainterExample extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final thickness = size.width * .25;
final Paint fillPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = thickness
..strokeCap = StrokeCap.round; // Add this
final Offset center = Offset(size.width / 2, size.height / 2);
final Rect arcRect =
Rect.fromCircle(center: center, radius: size.width - thickness);
canvas.drawArc(arcRect, 0, 270 * pi / 180, false, fillPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
When you draw a donut chart, the border is drawn on top of the arc. This causes the border to look thicker where the arcs meet. To fix this, you should draw the border with a slightly larger radius than the arc. This way, the border appears as a clean outline around the arc instead of overlapping it. Try this code
import 'dart:math';
import 'package:flutter/material.dart';
class DonutChartPainter extends CustomPainter {
final double planCalories;
final double leftCalories;
final double thickness = 40;
final Color green; // Add colors as parameters
final Color lightGreen;
DonutChartPainter(
this.planCalories, this.leftCalories, this.green, this.lightGreen);
@override
void paint(Canvas canvas, Size size) {
final Paint fillPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = thickness
..strokeCap = StrokeCap.butt;
final Paint borderPaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 1;
final double radius = size.width / 2;
final Offset center = Offset(size.width / 2, size.height / 2);
final double usedCalories = planCalories - leftCalories;
final double leftAngle = (leftCalories / planCalories) * 2 * pi;
final double usedAngle = (usedCalories / planCalories) * 2 * pi;
final double separationOffset = 10;
final Offset usedCenter = Offset(
center.dx + separationOffset * cos(-pi / 2 + usedAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle / 2));
final Offset leftCenter = Offset(
center.dx + separationOffset * cos(-pi / 2 + usedAngle + leftAngle / 2),
center.dy + separationOffset * sin(-pi / 2 + usedAngle + leftAngle / 2));
Rect usedOvalRect =
Rect.fromCircle(center: usedCenter, radius: radius - thickness / 2);
Rect leftOvalRect =
Rect.fromCircle(center: leftCenter, radius: radius - thickness / 2);
fillPaint.color = green;
canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, fillPaint);
fillPaint.color = lightGreen;
canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, fillPaint);
//-> Draw the border *slightly larger* to make it stand out
final double borderRadius = radius - thickness / 2;
final Rect usedBorderRect = Rect.fromCircle(center: usedCenter, radius: borderRadius );
final Rect leftBorderRect = Rect.fromCircle(center: leftCenter, radius: borderRadius);
canvas.drawArc(usedBorderRect, -pi / 2, usedAngle, false, borderPaint);
canvas.drawArc(leftBorderRect, -pi / 2 + usedAngle, leftAngle, false, borderPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
//Example usage in a Widget:
class MyDonutChart extends StatelessWidget {
final double planCalories;
final double leftCalories;
const MyDonutChart({Key? key, required this.planCalories, required this.leftCalories}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: DonutChartPainter(
planCalories,
leftCalories,
Colors.green, //-> Replace with your colors
Colors.lightGreen,
),
size: const Size(200, 200), //-> Adjust the size if needed
);
}
}