I'm trying to implement a circular cutout of an image and I am using drawAtlas for it. Here is my implementation so far:
canvas.drawAtlas(
image!,
[
/* Identity transform */
RSTransform.fromComponents(
rotation: 0.0,
scale: 1,
anchorX: 0,
anchorY: 0,
translateX: 0,
translateY: 0,
)
],
[
Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2),
radius: 200,
),
],
[],
null,
null,
Paint(),
);
While it does work, it paints a rectangular image. I want to paint a circular cutout of the same image with some strokeWidth
. Is it possible to do so using drawAtlas?
Excellent question! Although in your code, you are calling
Rect.fromCircle
to specify a clipping area, but it's still a rect (you are constructing a rect from a circle). ThedrawAtlas
method only supports clipping rectangular areas from a larger image, as you probably already found out.The key here is to use
canvas.clipRRect
to reduce the "allowed painting area". This is similar to adding a selection box in Photoshop. After doing this, anything that paints outside of the selection box will be ignored. In other words, by callingcanvas.clipRRect
, we will no longer be able to draw anything outside of the clipped area.Presumably, after drawing a circular atlas, you might still want to draw other things to the canvas. And for those other things, you probably won't want to be limited to the clipped circle. To solve this, we can use
canvas.saveLayer
to save the state of the canvas before clipping happens, then do the circular clipping, then draw the altas, then finally, callcanvas.restore
to restore the previously saved state. Essentially this would clear the clipping, allowing us to draw more things anywhere on the canvas if needed.Solution:
In short, the paint method might look something like this:
Demo:
In the demo, when you press the button, the app will take a screenshot of the Flutter Logo inside the grey gradient container, and use that as the
ui.image
data. Then it will do thedrawAtlas
to draw a circular portion of the image to canvas.Full demo code (paste everything to
main.dart
to run):