This sketch shows what the final result should look like:
- A
CustomPainter
fills itsCanvas
(yellow area) with a slightly translucent background color. (Amber with an opacity of 0.8 in the sketch). - The
CustomPainter
draws a rectangle onto the canvas. And here it's getting interesting: The rectangle should only change the alpha value of the background color drawn at the previous step. The idea is to highlight some points of interest, by fading some "holes" in and out (visualized by the smaller, darker rectangle inside the yellow rectangle in the sketch above).
In code it looks simple:
class Highlighter extends CustomPainter {
ValueListenable<double> valueListenable;
Color backgroundColor;
Highlighter({required this.valueListenable, this.backgroundColor = Colors.amber}) : super(repaint: valueListenable);
@override
void paint(Canvas canvas, Size size) {
Color colorHole = backgroundColor.withOpacity(0.40);
Paint holePainter = Paint();
holePainter.color = colorHole;
holePainter.blendMode = BlendMode.dstOut;
canvas.saveLayer(null, holePainter);
// Step 1: Draw the background:
canvas.drawColor(backgroundColor.withOpacity(0.80), BlendMode.srcOver);
// Step 2: Highlight a rectangle:
canvas.drawRect(const Rect.fromLTWH(100, 100, 100, 100), holePainter);
canvas.restore();
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Problem is, the colors ain't right:
canvas.DrawColor()
draws some shade of gray instead of Amber, although the holes appear to be ok.- Removing the
saveLayer()
/restore()
calls draws the background with the right color, but then the holes ain't transparent.
Question now is: After filling the canvas with a color, how can you set parts of it to translucent?
If there's a more efficient/performant way to do it, please let me now as well - getting rid of the saveLayer()
call would be great...
Any advise is welcome. Thank you.