美文网首页iOS开发Flutter探索
iOS开发Fultter探索-自定义的涂鸦画板(12)

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

作者: 泽泽伐木类 | 来源:发表于2020-06-25 17:13 被阅读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(),
                ),
              )
            )
          ],
        );
      }
    

    问题

    • shouldRepaint()并并不是我理解的方式来控制绘制的,有待研究
      我想要的效果是当我在foregroundPainter实时绘制时,painter不要触发绘制,当foregroundPainter结束后执行一次painter绘制,但绘制时需要setState(),这样两个painter都会执行,而且在paintershouldRepaint ()中无论返回trueorfalse都会发生绘制,问题?
    • 性能有待考量

    总结

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

    相关文章

      网友评论

        本文标题:iOS开发Fultter探索-自定义的涂鸦画板(12)

        本文链接:https://www.haomeiwen.com/subject/hvwsfktx.html