Flutter 36: 图解自定义 View 之 Canvas

作者: 阿策神奇 | 来源:发表于2019-03-09 15:08 被阅读39次

          小菜继续学习 Canvas 的相关方法:

    drawVertices 绘制顶点

          小菜上次没有整理 drawVertices 的绘制方法,这次补上;Vertice 即顶点,通过绘制多个顶点,在进行连线,多用于 3D 模型中;

          drawVertices 包括三个参数,第一个是顶点属性,根据不同属性线的连接方式也不同;第二个是混合模式,即线的颜色与背景色混合效果;第三个是画笔,小菜测试调整 Paint 线的粗细无法调整整体连线的粗细;

          小菜借用 A B C D E F G H I 顶点来简单介绍:

    1. VertexMode.triangles:每三个分割顶点相连,即 [A B C] [D E F] [G H I] 共 3 组;
    2. VertexMode.triangleStrip:每相邻的三个顶点相连,即 [A B C] [B C D] [C D E] [D E F] [E F G] [F G H] [G H I] 共 7 组;
    3. VertexMode.triangleFan:每相邻的两个顶点与首点相连,即 [A B C] [A C D] [A D E] [A E F] [A F G] [A G H] [A H I] 共 7 组;
    canvas.drawVertices(
        Vertices(VertexMode.triangles, [
          Offset(30, 30), Offset(30, 60),Offset(60, 60),
          Offset(90, 60), Offset(120, 60), Offset(120, 30),
          Offset(60, 90), Offset(60, 120), Offset(90, 120),
        ]),
        BlendMode.colorBurn, Paint()..color = Colors.red);
    
    canvas.drawVertices(
        Vertices(VertexMode.triangleStrip, [
          Offset(210, 30), Offset(210, 60), Offset(240, 60),
          Offset(270, 60), Offset(300, 60), Offset(300, 30),
          Offset(240, 90), Offset(240, 120), Offset(270, 120),
        ]),
        BlendMode.colorBurn, Paint()..color = Colors.green);
    
    canvas.drawVertices(
        Vertices(VertexMode.triangleFan, [
          Offset(120, 150), Offset(120, 180), Offset(150, 180),
          Offset(180, 180), Offset(210, 180), Offset(210, 150),
          Offset(150, 210), Offset(150, 240), Offset(180, 240),
        ]),
        BlendMode.colorBurn, Paint()..color = Colors.blue);
    

    画布操作

          小菜接下来介绍一下画布的基本操作,与 Android 很相似;

    scale 缩放

          scale 即缩放效果,缩放的是画布大小,可以设置缩放倍数,且缩放倍数会叠加;

    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    // 缩放
    canvas.scale(2);
    
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    // 缩放
    canvas.scale(0.25);
    
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    
    translate 平移

          translate 即平移,平移的也是画布,并非画布中子元素,两个参数分别为水平方向和竖直方向距离;

    canvas.drawLine(
        Offset(0, 0), Offset(60, 60),
        Paint()..color = Colors.red..strokeWidth = 2);
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    // 平移
    canvas.translate(30, 90);
    
    canvas.drawLine(
        Offset(0, 0), Offset(0, Screen.height),
        Paint()..color = Colors.blueGrey..strokeWidth = 2);
    canvas.drawLine(
        Offset(0, 0), Offset(Screen.width, 0),
        Paint()..color = Colors.blueGrey..strokeWidth = 2);
    canvas.drawLine(
        Offset(0, 0), Offset(60, 60),
        Paint()..color = Colors.red..strokeWidth = 2);
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0.style = PaintingStyle.stroke);
    
    rotate 旋转

          rotate 即旋转,原点为屏幕左上角,小菜为了效果先将画布平移一部分到屏幕中间在进行旋转测试,注意参数并非角度而是对应的 PI 值;

    canvas.drawLine(
        Offset(0, 0), Offset(60, 60),
        Paint()..color = Colors.red..strokeWidth = 2);
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    // 以当前原点旋转 90 度
    canvas.rotate(degToRad(90));
    
    canvas.drawLine(
        Offset(0, 0), Offset(60, 60),
        Paint()..color = Colors.green..strokeWidth = 2);
    canvas.drawRect(
        Rect.fromLTWH(60, 60, 90, 50),
        Paint()..color = Colors.green
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    
    skew 斜切

          skew 即斜切,两个参数为水平方向和竖直方向切度值,值为三角函数中的 tan 值,即 45 度时 tan 值为 1

    canvas.drawRect(
        Rect.fromLTWH(60, 0, 90, 50),
        Paint()..color = Colors.red
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    // 水平方向斜近 30 度,竖直方向不变
    canvas.skew(0.6, 0);
    
    canvas.drawRect(
        Rect.fromLTWH(60, 0, 90, 50),
        Paint()..color = Colors.green
          ..strokeWidth = 2.0..style = PaintingStyle.stroke);
    
    save/restore 保存/恢复

          save/savelayer 即保存当前画布,restore 即恢复当前画布,也可以理解为清空重新绘制;save/restore 可以多次,以栈的方式存储,可以通过进栈/出栈到当具体某一层;但是小菜测试时发现与 save/restore 需要成对出现,否则回报不匹配异常;

    canvas.clipRect(Rect.fromLTWH(40, 40, Screen.width - 80, Screen.width - 80));
    canvas.drawColor(Colors.green, BlendMode.srcIn);
    // 保存画布1
    canvas.save();
    
    canvas.clipRect(
        Rect.fromLTWH(60, 60, Screen.width - 120, Screen.width - 120));
    canvas.drawColor(Colors.grey, BlendMode.srcIn);
    // 保存画布2
    canvas.save();
    canvas.clipRect(
        Rect.fromLTWH(80, 80, Screen.width - 160, Screen.width - 160));
    canvas.drawColor(Colors.orange, BlendMode.srcIn);
    //  canvas.save();
    // 恢复画布1
    canvas.restore();
    // 恢复画布2
    canvas.restore();
    //  canvas.restore();
    canvas.drawColor(Colors.blue, BlendMode.srcIn);
    


          Canvas 非常强大,还有很多研究不透彻的地方,小菜仍在不断学习,有错误的地方烦请多多指点;如下是小菜公众号,欢迎闲来吐槽~

    公众号.jpg

    相关文章

      网友评论

        本文标题:Flutter 36: 图解自定义 View 之 Canvas

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