iOS开发Flutter探索

iOS开发Fultter探索-自定义的涂鸦画板(12)

2020-06-25  本文已影响0人  泽泽伐木类
qnz4d-vd1dz.gif

前言

今天看下Flutter中关于绘图相关的部件,这里主要用到的有:
CustomPaint()

  CustomPaint({
    this.painter,  
    this.foregroundPainter,
    this.size = Size.zero,
    this.isComplex = false,
    this.willChange = false,
    Widget child,
  }) 
}

内部需要接受一个painter,是CustomPainter类型,这里我们需要继承并创建一个CustomPainter子类,并传给painter,这里我创建了_BackDrawPainter子类,并重写了void paint(Canvas canvas, Size size)方式,这个方式是绘制的核心;当需要绘制的时候会触发paint()方法;shouldRepaint () 会在绘制前触发,这里可以通过一些逻辑判断来控制是否需要执行一次绘制;

class _BackDrawPainter extends CustomPainter {
  List<Path> linePaths;
  int drawType;
  _BackDrawPainter(this.linePaths, {this.drawType});
  int linesCount;
  @override
  void paint(Canvas canvas, Size size) {
//    print('_BackDrawPainter draw......');
    var custompPaint = Paint()
      ..style = PaintingStyle.stroke
      ..color = Colors.black
      ..isAntiAlias = true
      ..strokeJoin = StrokeJoin.round
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 2.0;
    for (int i = 0; i < linePaths.length; i++) {
      Path path = linePaths[i];
      canvas.drawPath(path, custompPaint);
    }
  }

  @override
  bool shouldRepaint(_BackDrawPainter oldDelegate) {
    return oldDelegate.linePaths.length != this.linePaths.length;
  }
}

同时我也给foregroundPainter,配置了CustomPainter,这里主要维护实时绘制时的处理:

class _RealDrawPainter extends CustomPainter {

  Path realPath;
  int realDrawType;

  _RealDrawPainter(this.realPath, {this.realDrawType});

  @override
  void paint(Canvas canvas, Size size) {
//    print('_RealDrawPainter draw...... $realPath');
    if (realPath != null) {
//      print('内部=>_RealDrawPainter draw...... $realPath');
      var paint = Paint()
        ..style = PaintingStyle.stroke //填充
        ..color = Colors.black
        ..strokeJoin = StrokeJoin.round
        ..strokeCap = StrokeCap.round
//        ..blendMode = BlendMode.colorDodge
        ..isAntiAlias = true
        ..strokeWidth = 2.0;
      canvas.drawPath(realPath, paint);
    }
  }
  @override
  bool shouldRepaint(_RealDrawPainter oldDelegate) {
    return realPath != null;
  }
}

其它的就是绘制部分了,通过GestureDetector()来接收并处理事件:

@override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        GestureDetector(
          onPanDown: (DragDownDetails details) {
            _currentPath = Path();
            if(_drawType == 0){//一般曲线
              _currentPath = Path.from(_currentPath)
                ..moveTo(details.localPosition.dx, details.localPosition.dy);
            }else if(_drawType == 1){//矩形
              _currentPath = Path.from(_currentPath)..addRect(Rect.fromPoints(details.localPosition, details.localPosition));
            }else if(_drawType == 2){//内切圆
              _currentPath = Path.from(_currentPath)..addOval(Rect.fromPoints(details.localPosition, details.localPosition));
            }else if(_drawType == 3){//正圆
              _currentPath = Path.from(_currentPath)..addArc(Rect.fromCircle(center: details.localPosition,radius: 0.0), 0, 2.0 * pi);
            }
            _startPoint = details.localPosition;
            setState(() {});
          },
          onPanUpdate: (DragUpdateDetails details) {
            if(_drawType == 0){//一般曲线
              _currentPath = Path.from(_currentPath)
                ..lineTo(details.localPosition.dx, details.localPosition.dy);
            }else if(_drawType == 1){//矩形
              _currentPath.reset();
              _currentPath = Path.from(_currentPath)..addRect(Rect.fromPoints(_startPoint, details.localPosition));
            }else if(_drawType == 2){//内切圆
              _currentPath.reset();
              _currentPath = Path.from(_currentPath)..addOval(Rect.fromPoints(_startPoint, details.localPosition));
            }else if(_drawType == 3){//正圆
              _currentPath.reset();
              Rect frame =  Rect.fromPoints(_startPoint, details.localPosition);
              double radius = sqrt(pow(frame.width,2) * pow(frame.height,2));
              print('radius:$radius');
              _currentPath = Path.from(_currentPath)..addArc(Rect.fromCircle(center: _startPoint,radius: radius*0.5), 0, 2.0 * pi);
            }
            setState(() {});
          },
          onPanEnd: (DragEndDetails details) {
              print('onPanEnd');
              linePathArray = List.from(linePathArray)..add(_currentPath);
              setState(() {});
              _currentPath = null;
          },
          child: ClipRect(
            child: Container(
              child: CustomPaint(
                painter: _BackDrawPainter(linePathArray,drawType: _drawType),
                foregroundPainter: _RealDrawPainter(_currentPath,realDrawType: _drawType),
                isComplex: true,
                willChange: true,
                child: Container(),
              ),
            ),
          )
        ),
        Positioned(
          width: 700,
          height: 40,
          bottom: 0,
          child: Container(
//            color: Colors.red,
            child: Row(
              children: _getButtons(),
            ),
          )
        )
      ],
    );
  }

问题

总结

参考文献:https://book.flutterchina.club/chapter10/custom_paint.html

上一篇 下一篇

猜你喜欢

热点阅读