Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to erase/clip from Canvas CustomPaint?

I have already tried to use Canvas.clipPath along with GestureDetector to be like eraser on the canvas where i use the CustomPaint inside a Container with imageDecoration set, so i thought maybe there is another workaround this by using Canvas.drawPath along setting

 final Paint _eraserPaint = Paint()
    ..color = Colors.transparent
    ..blendMode = BlendMode.clear
    ..strokeWidth = 8
    ..style = PaintingStyle.stroke
    ..isAntiAlias = true;

but it draws black lines instead of erasing

any idea how to get around this?

thanks

like image 672
Mohammad Ersan Avatar asked Jan 07 '20 10:01

Mohammad Ersan


People also ask

What is saveLayer in Flutter?

saveLayer method Null safety blendMode applied. This lets you create composite effects, for example making a group of drawing commands semi-transparent. Without using saveLayer, each part of the group would be painted individually, so where they overlap would be darker than where they do not.

What is canvas Flutter?

Like an artist's canvas is a physical surface to draw on, a Canvas in Flutter is a virtual surface for drawing. But unlike a regular art canvas, you can't paint on the Flutter canvas with physical brushes. Flutter Canvas uses a two-point (x and y) coordinate system to determine the position of a point on the screen.

How do you use custom painters in Flutter?

Custom Painter is : A widget that provides a canvas on which to draw during the paint phase. :To paint in Flutter you can use the CustomPaint widget which basically takes size of its parent if not given the child . The CustomPainter subclass overrides two methods: paint() and shouldRepaint() .


2 Answers

The key is to call saveLayer before drawing anything that might require erasing. After that's done (thus creating a new layer for you to use), you can then draw with any Color to fill, or draw with BlendMode.clear to erase. Lastly, call restore to "merge" the new layer into other existing layers.

For example, let's draw a red square and subtract a circle from it:

void paint(Canvas canvas, Size size) {
  canvas.saveLayer(Rect.largest, Paint());
  canvas.drawRect(Rect.fromLTWH(0, 0, 80, 80), Paint()..color = Colors.red);
  canvas.drawCircle(Offset(40, 40), 40, Paint()..blendMode = BlendMode.clear);
  canvas.restore();
}

Sample result:

A square with a circle cut in the middle

like image 59
user1032613 Avatar answered Oct 21 '22 07:10

user1032613


May this code can help you!

class DrawingPainter extends CustomPainter {

  List<DrawingPoints> pointsList;
  List<Offset> offsetPoints = List();
  
  DrawingPainter({
    this.pointsList,
  });

  @override
  void paint(Canvas canvas, Size size) {
    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
    for (int i = 0; i < pointsList.length - 1; i++) {
      if (pointsList[i] != null && pointsList[i + 1] != null) {
        canvas.drawLine(pointsList[i].points, pointsList[i + 1].points, pointsList[i].paint);
        canvas.drawCircle(pointsList[i].points, pointsList[i].paint.strokeWidth/2, pointsList[i].paint);
      }
    }
    canvas.restore();
  }

  @override
  bool shouldRepaint(DrawingPainter oldDelegate) => true;
}

class DrawingPoints {
  Paint paint;
  Offset points;
  DrawingPoints({this.points, this.paint});
}

You need saveLayer, then restores to save Paint

Maybe you need to add this code to te Statefull widget.

void changeBrush(bool isErease){
    setState(() {
      if ( isErease ){
        paint = Paint();
        paint.blendMode = BlendMode.clear;
        paint.color = Colors.white;
        paint.strokeWidth = strokeWidth;
      }else{
        paint = Paint();
        paint.isAntiAlias = true;
        paint.color = selectedColor.withOpacity(opacity);
        paint.strokeWidth = strokeWidth;
      }
    });
  }
like image 30
Santiago Alcazar Avatar answered Oct 21 '22 06:10

Santiago Alcazar