微信交流群

# 画板

画板效果如下:

画板的实现分为两个步骤:

  1. 记录用户滑动的路径。
  2. 根据滑动路径绘制。

使用 Listener 记录用户滑动的路径:

class DrawingBoard extends StatefulWidget {
  
  _DrawingBoardState createState() => _DrawingBoardState();
}

class _DrawingBoardState extends State<DrawingBoard> {
  List<List<Offset>> _path = [];

  
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (PointerDownEvent pointerDownEvent) {
        setState(() {
          _path.add([pointerDownEvent.localPosition]);
        });
      },
      onPointerMove: (PointerMoveEvent pointerMoveEvent) {
        setState(() {
          _path[_path.length-1].add(pointerMoveEvent.localPosition);
        });
      },
      onPointerUp: (PointerUpEvent pointerUpEvent) {
        setState(() {
          _path[_path.length-1].add(pointerUpEvent.localPosition);
        });
      },
      onPointerCancel: (PointerCancelEvent pointerCancelEvent) {
        setState(() {
          _path[_path.length-1].add(pointerCancelEvent.localPosition);
        });
      },
      child: Container(
        width: double.infinity,
        height: double.infinity,
        child: CustomPaint(
          painter: DrawingBoardPainter(_path),
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

绘制路径:

class DrawingBoardPainter extends CustomPainter {
  final List<List<Offset>> path;

  DrawingBoardPainter(this.path);

  Paint _paint = Paint()
    ..color = Colors.red
    ..style = PaintingStyle.stroke
    ..strokeWidth = 3;

  
  void paint(Canvas canvas, Size size) {
    path.forEach((list) {
      Path _path = Path();
      for (int i = 0; i < list.length; i++) {
        if (i == 0) {
          _path.moveTo(list[i].dx, list[i].dy);
        } else {
          _path.lineTo(list[i].dx, list[i].dy);
        }
      }
      canvas.drawPath( _path, _paint);
    });
  }

  
  bool shouldRepaint(DrawingBoardPainter oldDelegate) {
    return true;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

搞定,是不是非常简单,其他一些画板的功能,比如绘制圆形、矩形等都是类似的思路。