Flutter 绘制 Tiled Lines

前言

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

建立画布

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

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; }  复制代码

绘制线条

建立好画布后在 TiledLinesPainterpaint 方法里进行绘制。添加一个 _drawLine 方法用来绘制线条,绘制线条须要起始点和终止点,经过参数将数值传入。less

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 方法就有了绘制不一样方向的线条的能力。dom

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 将画布分割为多个小的方格,在每一个小的方格里面绘制线条。编辑器

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) 复制代码

绘制边框和阴影

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

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 Linespost

本文使用 mdnice 排版ui

相关文章
相关标签/搜索