0

我正在研究要在我的应用程序中使用的绘图功能。我尝试按照这个答案来实现橡皮擦功能。它工作正常,但我面临的问题是,当我再次选择钢笔工具绘制点时,使用橡皮擦工具擦除绘制的点后,它不会在已擦除的区域上绘制。例如:

  • 我用手指在屏幕上绘图(启用钢笔工具)
  • 我用手指擦除屏幕上的绘制区域(启用橡皮擦工具)
  • 我再次选择钢笔工具并用手指在屏幕上绘制,但这不会在已擦除区域上绘制点。有什么办法可以解决这个问题?

这是我到目前为止实现的代码:

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_colorpicker/flutter_colorpicker.dart';

enum Tool { PEN, ERASER }

class DrawingData {
  Offset point;
  Paint paint;

  DrawingData({this.point, this.paint});
}

class MyDrawing extends StatefulWidget {
  @override
  _MyDrawingState createState() => _MyDrawingState();
}

class _MyDrawingState extends State<MyDrawing> {
  List<DrawingData> penPoints = [];
  List<DrawingData> eraserPoints = [];
  Color selectedColor;
  double strokeWidth;
  Tool tool = Tool.PEN;

  @override
  void initState() {
    super.initState();
    selectedColor = Colors.black;
    strokeWidth = 5.0;

    SystemChrome.setEnabledSystemUIOverlays([]);
  }

  void selectColor() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Select a color'),
          content: SingleChildScrollView(
            child: BlockPicker(
              pickerColor: selectedColor,
              onColorChanged: (color) {
                this.setState(() {
                  selectedColor = color;
                });
              },
            ),
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text('Close'),
            ),
          ],
        );
      },
    );
  }

  void _addPenPoints(details) {
    setState(() {
      penPoints.add(DrawingData(
          point: details.localPosition,
          paint: Paint()
            ..strokeCap = StrokeCap.round
            ..isAntiAlias = true
            ..color = selectedColor
            ..strokeWidth = strokeWidth
            ..blendMode = BlendMode.color));
    });
  }

  void _addEraserPoints(details) {
    setState(() {
      eraserPoints.add(DrawingData(
          point: details.localPosition,
          paint: Paint()
            ..strokeCap = StrokeCap.round
            ..isAntiAlias = true
            ..color = selectedColor
            ..strokeWidth = strokeWidth
            ..blendMode = BlendMode.clear));
    });
  }

  @override
  Widget build(BuildContext context) {
    final double width = MediaQuery.of(context).size.width;
    final double height = MediaQuery.of(context).size.height;

    Widget drawingArea = Center(
      child: Container(
        width: width,
        height: height,
        child: GestureDetector(
          onPanDown: tool == Tool.PEN ? _addPenPoints : _addEraserPoints,
          onPanUpdate: tool == Tool.PEN ? _addPenPoints : _addEraserPoints,
          onPanEnd: tool == Tool.PEN
              ? (details) {
                  setState(() {
                    penPoints.add(null);
                  });
                }
              : (details) {
                  setState(() {
                    eraserPoints.add(null);
                  });
                },
          child: CustomPaint(
            painter: MyCustomPainter(
              penPoints: penPoints,
              eraserPoints: eraserPoints,
              tool: tool,
            ),
          ),
        ),
      ),
    );

    Widget drawingSettings = Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Container(
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.all(Radius.circular(11.0)),
              ),
              child: Row(
                children: [
                  IconButton(
                    icon: Icon(
                      Icons.brush,
                      color: tool == Tool.PEN ? selectedColor : Colors.black,
                    ),
                    onPressed: () {
                      setState(() {
                        tool = Tool.PEN;
                      });
                    },
                  ),
                  IconButton(
                    icon: Icon(
                      Icons.color_lens,
                      color: selectedColor,
                    ),
                    onPressed: () {
                      selectColor();
                    },
                  ),
                  Slider(
                    min: 1.0,
                    max: 11.0,
                    label: "Stroke $strokeWidth",
                    activeColor: selectedColor,
                    value: strokeWidth,
                    onChanged: (value) {
                      setState(() {
                        strokeWidth = value;
                      });
                    },
                  ),
                  IconButton(
                    icon: Icon(
                      Icons.remove_circle,
                      color: tool == Tool.ERASER ? selectedColor : Colors.black,
                    ),
                    onPressed: () {
                      setState(() {
                        tool = Tool.ERASER;
                      });
                    },
                  ),
                  IconButton(
                    icon: Icon(
                      Icons.layers_clear,
                      color: Colors.black,
                    ),
                    onPressed: () {
                      setState(() {
                        penPoints.clear();
                        eraserPoints.clear();
                      });
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ],
    );

    return Stack(
      children: [
        drawingArea,
        drawingSettings,
      ],
    );
  }
}

class MyCustomPainter extends CustomPainter {
  List<DrawingData> penPoints;
  List<DrawingData> eraserPoints;
  Tool tool;

  MyCustomPainter(
      {@required this.penPoints,
      @required this.eraserPoints,
      @required this.tool});

  @override
  void paint(Canvas canvas, Size size) {
    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());

    for (int x = 0; x < penPoints.length - 1; x++) {
      if (penPoints[x] != null && penPoints[x + 1] != null) {
        canvas.drawLine(
            penPoints[x].point, penPoints[x + 1].point, penPoints[x].paint);
      } else if (penPoints[x] != null && penPoints[x + 1] == null) {
        canvas.drawPoints(
            PointMode.points, [penPoints[x].point], penPoints[x].paint);
      }
    }

    for (int x = 0; x < eraserPoints.length - 1; x++) {
      if (eraserPoints[x] != null && eraserPoints[x + 1] != null) {
        canvas.drawLine(eraserPoints[x].point, eraserPoints[x + 1].point,
            eraserPoints[x].paint);
      } else if (eraserPoints[x] != null && eraserPoints[x + 1] == null) {
        canvas.drawPoints(
            PointMode.points, [eraserPoints[x].point], eraserPoints[x].paint);
      }
    }

    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

4

0 回答 0