美文网首页
自定义View项目实战(一):Canvas与Paint基础

自定义View项目实战(一):Canvas与Paint基础

作者: bug音音 | 来源:发表于2020-12-16 10:36 被阅读0次
    本文重点

    着重介绍自绘控件,因为所有的widget归根结底都是使用canvas和paint来绘制的,理解了二者,对于其他的widget原理有溯源的功效。

    • Canvas:画布
    • Paint:画笔
      怎么做?
    • 继承CustomPainter
    • 重写paint方法与shouldRepaint方法
    • paint提供来canvas和size,canvas用于绘制,size用于确定大小
    • shouldRepaint用于确认是否每次都重新绘制
    画矩形canvas.drawRect();
    void drawRect(Rect rect, Paint paint)
    
    

    rect 矩形的描述

    • Rect.fromCenter({ Offset center, double width, double height }),根据中心点和宽高,定义一个矩形。

    • Rect.fromCircle({ Offset center, double radius }),根据中心点和半径定义一个矩形

    • Rect.fromLTRB(this.left, this.top, this.right, this.bottom),left左边框距离左边的距离,top上边框距离上边的距离,right右边框距离左边的距离,bottom下边框距离上边的距离。根据这四个值定义一个矩形。

    • Rect.fromLTWH(double left, double top, double width, double height),根据左上角顶点和宽高定义一个矩形。

    • Rect.fromPoints(Offset a, Offset b),根据左上角顶点和右下角顶点定义一个矩形。
      示例:

      image
    class _MyHomePageState extends State<MyHomePage> {
      bool flag = true;
    
      void change(bool value) {
        setState(() {
          flag = value;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: CustomPaint(
              size: Size(380, 560),
              painter: MyPainter(),
            ),
          ),
        );
      }
    }
    
    class MyPainter extends CustomPainter{
    
      @override
      void paint(Canvas canvas, Size size) {
        test01(canvas, size);
      }
    
      void test00(Canvas canvas, Size size) {
        var paint = new Paint()
            ..color = Colors.orange[200]
            ..style = PaintingStyle.fill
            ..isAntiAlias = true;
        // 画矩形
        canvas.drawRect(Offset.zero & size, paint);
        paint
        ..color = Colors.green;
        canvas.drawRect(Rect.fromCenter(width: 200,height: 200,center: Offset(150, 150)), paint);
    
        paint
          ..color = Colors.blue;
        canvas.drawRect(Rect.fromCircle(radius: 50,center: Offset(150, 150)), paint);
    
        paint
          ..color = Colors.redAccent;
        canvas.drawRect(Rect.fromLTRB(10,10,200,100), paint);
    
        paint
          ..color = Colors.pink;
        canvas.drawRect(Rect.fromLTWH(10,250,100,100), paint);
    
        paint
          ..color = Colors.grey;
        canvas.drawRect(Rect.fromPoints(Offset(250, 250),Offset(350, 300)), paint);
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return true;
      }
    
    }
    
    
    画圆角矩形canvas.drawRRect
    image
    void test01(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
    
        Rect rect = Rect.fromCircle(
            center: Offset(200, 200), radius: 150);
        RRect rRect = RRect.fromRectAndRadius(rect, Radius.circular(30));
        canvas.drawRRect(rRect, paint);
      }
    
    
    画环形圆角矩形canvas.drawDRRect
    image
    void test011(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        Rect rect1 = Rect.fromCircle(
            center: Offset(200, 200), radius: 140);
        Rect rect2 = Rect.fromCircle(
            center: Offset(200, 200), radius: 160);
        RRect rRect1 = RRect.fromRectAndRadius(rect1, Radius.circular(20));
        RRect rRect2 = RRect.fromRectAndRadius(rect2, Radius.circular(20));
        canvas.drawDRRect(rRect2, rRect1, paint);
      }
    
    
    画圆canvas.drawCircle
    drawCircle(Offset c, double radius, Paint paint)
    
    
    • c 中心点
    • radius 圆半径
    • paint 画笔

    示例:

    image
    void test02(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        canvas.drawRect(Offset.zero & size, paint);
    
        paint ..color = Colors.blue[200];
        canvas.drawCircle(Offset(200, 200), 100, paint);
      }
    
    
    画椭圆canvas.drawOval
    image
    void test022(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        canvas.drawRect(Offset.zero & size, paint);
    
        paint..color = Colors.blue[200];
        canvas.drawOval(
            Rect.fromCenter(width: 200, height: 300, center: Offset(150, 250)),
            paint);
      }
    
    
    画线canvas.drawLine
    void drawLine(Offset p1, Offset p2, Paint paint)
    
    
    • p1 线的起点
    • p2 线的终点

    注意:

    • 画笔的style 更改为PaintingStyle.stroke
    • 可以调整线的粗细 strokeWidth = 3

    示例:

    image
    void test03(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        canvas.drawRect(Offset.zero & size, paint);
    
        paint
          ..color = Colors.black
          ..strokeWidth = 3
          ..style = PaintingStyle.stroke;
        canvas.drawLine(Offset(100, 150), Offset(250, 150), paint);
    
      }
    
    
    画颜色canvas.drawColor
    void drawColor(Color color, BlendMode blendMode)
    
    
    • blendMode 是颜色的混合模式

      image
    void test04(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
    
        canvas.drawColor(Colors.blue[200], BlendMode.srcIn);
        canvas.drawRect(Offset.zero & size/2, paint);
    
      }
    
    
    画点drawPoints
    image

    参数PointModel:

    • ui.PointMode.points,// 单独的点
    • ui.PointMode.polygon,// 所有的点按给定顺序连成线
    • ui.PointMode.lines,//画一条线,起始点为给定数组的前两个点
    void test06(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        canvas.drawRect(Offset.zero & size, paint);
        paint
          ..style = PaintingStyle.stroke
          ..strokeWidth = 15
          ..strokeCap = StrokeCap.round
          ..color = Colors.black;
        canvas.drawPoints(
    //        ui.PointMode.points,// 单独的点
    //    ui.PointMode.polygon,// 所有的点按给定顺序连成线
        ui.PointMode.lines,//画一条线,起始点为给定数组的前两个点
            [Offset(100, 100), Offset(300, 100), Offset(200, 300)], paint);
      }
    
    
    画路径canvas.drawPath

    paint ..color = PaintingStyle.fill;

    image
    void test07(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..isAntiAlias = true;
        // 画矩形
        Path path = Path();
        path.moveTo(100, 100);
        path.lineTo(100, 200);
        path.lineTo(200, 100);
        path.lineTo(200, 200);
        canvas.drawPath(path, paint);
      }
    
    

    paint ..color = PaintingStyle.stroke;

    image
    void test07(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
    //      ..style = PaintingStyle.fill
          ..style = PaintingStyle.stroke
          ..strokeWidth = 5
          ..isAntiAlias = true;
        // 画矩形
        Path path = Path();
        path.moveTo(100, 100);
        path.lineTo(100, 200);
        path.lineTo(200, 100);
        path.lineTo(200, 200);
        canvas.drawPath(path, paint);
      }
    
    

    path.close()

    image
    void test07(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
    //      ..style = PaintingStyle.fill
          ..style = PaintingStyle.stroke
          ..strokeWidth = 5
          ..isAntiAlias = true;
        // 画矩形
        Path path = Path();
        path.moveTo(100, 100);
        path.lineTo(100, 200);
        path.lineTo(200, 100);
        path.lineTo(200, 200);
        path.close();
        canvas.drawPath(path, paint);
      }
    
    
    画弧型
    void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
    
    
    • rect 弧所属椭圆的外接矩形,用于定位该弧的位置

    • startAngle,起始角度,按弧度制,顺时针

    • sweepAngle,画多少弧度,一个圆的弧度是 2PI,也就是2*3.14

    • useCenter,是否将弧与中心连接,形成一个扇形

      image
    void test08(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
    //      ..style = PaintingStyle.fill
          ..style = PaintingStyle.stroke
          ..strokeWidth = 5
          ..isAntiAlias = true;
        Rect rect = Rect.fromCircle(
            center: Offset(200, 200), radius: 100);
        canvas.drawArc(rect, 0, 3.14, false, paint);
      }
    
    
    画阴影drawShadow
    void drawShadow(Path path, Color color, double elevation, bool transparentOccluder)
    
    
    • path 阴影区域

    • color 阴影颜色

    • elevation 阴影高度,一般是向右下

    • transparentOccluder 如果阻塞对象不是不透明的,则阻塞“transparentoccluder”参数应为true.百度翻译的,没明白啥意思

      image
    void test09(Canvas canvas, Size size) {
        var paint = new Paint()
          ..color = Colors.orange[200]
          ..style = PaintingStyle.fill
          ..strokeWidth = 5
          ..isAntiAlias = true;
        Path path = Path();
        path.moveTo(100, 100);
        path.lineTo(100, 200);
        path.lineTo(200, 100);
        path.lineTo(200, 200);
        canvas.drawPath(path, paint);
        canvas.drawShadow(path, Colors.orange, 10, true);
      }
    

    相关文章

      网友评论

          本文标题:自定义View项目实战(一):Canvas与Paint基础

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