How do I "cut a hole" in a shape with flutter canvas? I have this rather complex set of shapes that is made to look like a real world object. This object has a hole in it shaped like a rounded rectangle.
I would really like to subtract a RRect from a shape, but I cannot find any information on how to do this.
canvas.clipRRect(myRRect)
just removes everything that is not covered by myRRect
. I want the opposite of that. i.e. to make a myRRect
shape hole in the current canvas shape or shapes.
You can use Path.combine
along with the difference
operation to create the hole.
The custom painter :
class HolePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint();
paint.color = Colors.blue;
canvas.drawPath(
Path.combine(
PathOperation.difference,
Path()..addRRect(RRect.fromLTRBR(100, 100, 300, 300, Radius.circular(10))),
Path()
..addOval(Rect.fromCircle(center: Offset(200, 200), radius: 50))
..close(),
),
paint,
);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
Usage :
class EditAvatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hole in rounded rectangle'),
),
body: CustomPaint(
painter: HolePainter(),
child: Container(),
),
}
}
Result :
Of course if you want the hole to be a rounded rect simply substract an RRect
instead of a Circle
.
A solution is to use PathFillType.evenOdd
:
// circle with empty RRect inside
final Path path = Path();
path.fillType = PathFillType.evenOdd;
path.addOval(Rect.fromCircle(center: center, radius: radius));
path.addRRect(RRect.fromRectAndRadius(
Rect.fromCircle(center: center, radius: radius / 2),
Radius.circular(radius / 10)));
canvas.drawPath(path, paint);
You can try with different BlendMode in Custom Painter, Below is one of the example which you can refer:
class MyPaint extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// below one is big circle and instead of this circle you can draw your shape here.
canvas.drawCircle(Offset(200, 200), 100, Paint()
..color = Colors.orange[200]
..style = PaintingStyle.fill);
// below the circle which you want to create a cropping part.
RRect rRect = RRect.fromRectAndRadius(Rect.fromCenter(center: Offset(200, 200), width: 75, height: 75), Radius.circular(8));
canvas.drawRRect(rRect, Paint()
..color = Colors.orange[200]
..style = PaintingStyle.fill
..blendMode = BlendMode.dstOut);
canvas.save();
canvas.restore();
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Here, I have used BlendMode.dstOut
which will be used to show the destination sources, but only where the two sources do not overlap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With