IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Flutter 绘制瓷砖线 Tiled Lines

    冷石发表于 2022-08-29 09:01:22
    love 0

    前几天发现了一个使用 <canvas> 绘制图形的教程 generative artistry 感觉很有意思,尝试用 Flutter 实现。本文实现第一篇教程的图形 Tiled Lines 效果如下。

    前言

    前几天发现了一个使用 <canvas> 绘制图形的教程 generative artistry 感觉很有意思,尝试用 Flutter 实现。本文实现第一篇教程的图形 Tiled Lines 效果如下。

    创建画布

    首先使用一个 Container 控件创建一个 320*320 大小的绘制区域,添加 CustomPaint 画布和一个继承 CustomPainter
    的画笔 TiledLinesPainter。关于 CustomPaint 和 CustomPainter 的知识可以查阅这篇文章 使用 Flutter 绘制图表(一)柱状图 📊。

    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
    import 'package:flutter/material.dart';

    class TiledLines extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Container(
    width: 320.0,
    height: 320.0,
    decoration: BoxDecoration(
    border: Border.all(
    color: Colors.black,
    width: 1.0,
    ),
    ),
    child: CustomPaint(
    painter: TiledLinesPainter(),
    ),
    ),
    ),
    );
    }
    }

    class TiledLinesPainter extends CustomPainter {
    @override
    void paint(Canvas canvas, Size size) {}

    bool shouldRepaint(TiledLinesPainter oldDelegate) => false;
    }

    绘制线条

    创建好画布后在 TiledLinesPainter 的 paint 方法里进行绘制。添加一个 _drawLine 方法用来绘制线条,绘制线条需要起始点和终止点,通过参数将数值传入。

    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
    class TiledLinesPainter extends CustomPainter {
    void _drawLine(
    Canvas canvas,
    double x,
    double y,
    double width,
    double height,
    ) {
    final Paint paint = Paint()
    ..strokeCap = StrokeCap.square
    ..strokeWidth = 2;

    Offset p1 = Offset(x, y);
    Offset p2 = Offset(x + width, y + height);

    canvas.drawLine(p1, p2, paint);
    }

    @override
    void paint(Canvas canvas, Size size) {
    _drawLine(canvas, 0, 0, size.width, size.height);
    }

    bool shouldRepaint(TiledLinesPainter oldDelegate) => false;
    }

    加入随机性

    使用 Random().nextBool() 方法创建一个随机的布尔值,在绘制线条之前改变起始点和终止点的坐标,这样 _drawLine 方法就有了绘制不同方向的线条的能力。

    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
    void _drawLine(
    Canvas canvas,
    double x,
    double y,
    double width,
    double height,
    ) {
    final bool isLeftToRight = Random().nextBool();

    final Paint paint = Paint()
    ..strokeCap = StrokeCap.square
    ..strokeWidth = 2;

    Offset p1;
    Offset p2;

    if (isLeftToRight) {
    p1 = Offset(x, y);
    p2 = Offset(x + width, y + height);
    } else {
    p1 = Offset(x + width, y);
    p2 = Offset(x, y + height);
    }

    canvas.drawLine(p1, p2, paint);
    }

    绘制更多的线条

    可以绘制更多的线条喽!给 TiledLinesPainter 添加一个 step 属性,表示在画布上每隔多长距离绘制一条线。使用 step 将画布分割为多个小的方格,在每个小的方格里面绘制线条。

    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
    42
    43
    44
    45
    46
    47
    class TiledLinesPainter extends CustomPainter {
    final double step;

    TiledLinesPainter(this.step);

    void _drawLine(
    Canvas canvas,
    double x,
    double y,
    double width,
    double height,
    ) {
    final bool isLeftToRight = Random().nextBool();

    final Paint paint = Paint()
    ..strokeCap = StrokeCap.square
    ..strokeWidth = 2;

    Offset p1;
    Offset p2;

    if (isLeftToRight) {
    p1 = Offset(x, y);
    p2 = Offset(x + width, y + height);
    } else {
    p1 = Offset(x + width, y);
    p2 = Offset(x, y + height);
    }

    canvas.drawLine(p1, p2, paint);
    }

    @override
    void paint(Canvas canvas, Size size) {
    for (double x = 0; x < size.width; x += step) {
    for (double y = 0; y < size.height; y += step) {
    _drawLine(canvas, x, y, step, step);
    }
    }
    }

    bool shouldRepaint(TiledLinesPainter oldDelegate) => false;
    }

    //...

    TiledLinesPainter(20)

    绘制边框和阴影

    最后给画布添加边框和阴影效果,大功告成!👏 感谢阅读。

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    import 'dart:math';
    import 'package:flutter/material.dart';

    class TiledLines extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    List<BoxShadow> shadows = [];
    double opacity = 0.1;

    // 添加画布阴影
    for (double i = 1; i <= 16; i++) {
    opacity -= 0.01;
    opacity = opacity > 0.01 ? opacity : 0.01;

    shadows.add(
    BoxShadow(
    offset: Offset(-i, i),
    color: Color.fromRGBO(0, 0, 0, opacity),
    blurRadius: 2,
    spreadRadius: 1,
    ),
    );
    }

    return Scaffold(
    body: Center(
    child: Container(
    width: 320.0,
    height: 320.0,
    decoration: BoxDecoration(
    // 添加画布边框
    border: Border.all(
    color: Colors.black,
    width: 20.0,
    ),
    boxShadow: shadows,
    ),
    child: Container(
    color: Colors.white,
    padding: const EdgeInsets.all(20.0),
    child: CustomPaint(
    painter: TiledLinesPainter(20),
    ),
    ),
    ),
    ),
    );
    }
    }

    class TiledLinesPainter extends CustomPainter {
    final double step;

    TiledLinesPainter(this.step);

    void _drawLine(
    Canvas canvas,
    double x,
    double y,
    double width,
    double height,
    ) {
    // 创建随机性
    final bool isLeftToRight = Random().nextBool();

    final Paint paint = Paint()
    ..strokeCap = StrokeCap.square
    ..strokeWidth = 2;

    Offset p1;
    Offset p2;

    // 设置线条的起始点和终止点
    if (isLeftToRight) {
    p1 = Offset(x, y);
    p2 = Offset(x + width, y + height);
    } else {
    p1 = Offset(x + width, y);
    p2 = Offset(x, y + height);
    }

    canvas.drawLine(p1, p2, paint);
    }

    @override
    void paint(Canvas canvas, Size size) {
    // 使用 step 分割画布,创建小的绘制方格
    for (double x = 0; x < size.width; x += step) {
    for (double y = 0; y < size.height; y += step) {
    _drawLine(canvas, x, y, step, step);
    }
    }
    }

    bool shouldRepaint(TiledLinesPainter oldDelegate) => false;
    }

    参考

    Tiled Lines



沪ICP备19023445号-2号
友情链接