上一篇文章中,简单介绍了使用CustomPainter实现一个简单的画板demo,其中只是对于drawLine画线做了应用,这篇文章,再去学习一下painting中的其他方法。
这里提一下,自定义的CustomPainter需要放在CustomPaint中才能展示,赋值给painter属性,CustomPainter也还有一个child
const CustomPaint({
Key key,
this.painter,
this.foregroundPainter,
this.size = Size.zero,
this.isComplex = false,
this.willChange = false,
Widget child,
})
先看第一个例子,画一个表格,作为我们后续学习的背景,这里还试了一下加一个child之后的效果,就是下面右侧那个效果图
Widget build(BuildContext context) {
return Container(
child: Center(
child: CustomPaint(
painter: GirdPainter(10),
size: Size(300, 300),
child: new Text('dataaaaaaaaaaaaaa'),
),
),
);
}
可以看到child和我们绘制的东西是重叠的
画表格的代码如下,就比较简单了,还是drawLine
class GirdPainter extends CustomPainter {
int count;
GirdPainter(this.count);
@override
void paint(Canvas canvas, Size size) {
double w = size.width / count;
double h = size.height / count;
Paint _paint = new Paint()
..color = Colors.yellow[100]
..style = PaintingStyle.stroke
..strokeWidth = 1.0;
// TODO: implement paint
for (var i = 0; i <= count; i++) {
double dx = w * i;
double dy = h * i;
//画横线
canvas.drawLine(Offset(0, dy), Offset(size.width, dy), _paint);
canvas.drawLine(Offset(dx, 0), Offset(dx, size.height), _paint);
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return false;
}
}
顺便说一下style属性,是个枚举,只有两个值,fill是用来填充的,stroke是用来画线的,需要制定一下线的宽度(strokeWidth)
enum PaintingStyle {
fill,
stroke,
}
接下来试一下fill的效果,画一个矩形
void paint(Canvas canvas, Size size) {
double w = size.width / count;
double h = size.height / count;
Paint _bgPaint = new Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
canvas.drawRect(Offset.zero & size, _bgPaint);
}
这里需要了解一下drawRect(Rect rect, Paint paint)的第一个参数Rect的构建:
// 利用矩形左边的X坐标、矩形顶部的Y坐标、矩形右边的X坐标、矩形底部的Y坐标确定矩形的大小和位置
Rect.fromLTRB(doubleleft, doubletop, doubleright, doublebottom)
// 利用矩形的左边的X轴、顶边的Y轴位置配合设置矩形的长和宽来确定矩形的大小和位置
Rect.fromLTWH(doubleleft, doubletop, doublewidth, doubleheight)
// 利用矩形的中心点和矩形所在圆的半径来确定矩形的大小和位置,此方法确定的是一个正方形
Rect.fromCircle({ Offset center, doubleradius })
// 利用矩形的左上角和右下角的坐标确定矩形的大小和位置
// 需要注意的是两点坐标中,如果X轴相同或者Y轴相同,确定的是一条线,
// 如果两点XY坐标都是同一个数字,确定的是一个点。
Rect.fromPoints(Offset a, Offset b)
学习到这里突然想起来,还从来没有画过点呢,直接就开始画线,画矩形了,还是得试试点是咋画的?,就在刚才这个蓝色矩形上画几个试试吧
List<Offset> points = [
Offset(0, 0),
Offset(30, 50),
Offset(20, 80),
Offset(100, 40),
Offset(150, 90),
Offset(60, 110),
Offset(260, 160),
];
var _pointPaint = Paint()
..color = Color(0xFFFf0000)
..strokeWidth = 5;
canvas.drawPoints(PointMode.points, points, _pointPaint);
这里PointMode 也是个枚举 ,有三个值,想知道都是啥意思呢?把每个都试试就知道了?
enum PointMode {
points,
lines,
polygon,
}
看三个枚举分别的效果图,是不是就一目了然了,然后我们继续~
再画个圆,给个圆心和半径
var _circlePaint = new Paint()
..color = Colors.red
..strokeWidth = 2
..style = PaintingStyle.stroke;
canvas.drawCircle(Offset(100, 100), 50, _circlePaint);
会画圆了再试着画一段圆弧,先看下画圆弧需要的参数
// rect:矩形区域
// startAngle:开始的弧度
// sweepAngle:扫过的弧度,正数顺时针,负数逆时针
// useCenter:是否使用中心点绘制 如果usecenter为真,则弧为
///回到中心,形成一个圆扇形。否则,弧为
///未闭合,形成圆段。
void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint) {
assert(_rectIsValid(rect));
assert(paint != null);
_drawArc(rect.left, rect.top, rect.right, rect.bottom, startAngle,
sweepAngle, useCenter, paint._objects, paint._data);
}
说了一堆,不如自己画一个看的更明白? 因为弧度要设计到π 所以先
import 'dart:math';
var _circlePaint = new Paint()
..color = Colors.red
..strokeWidth = 2
..style = PaintingStyle.stroke;
var rect = Rect.fromCircle(center: Offset(100.0, 100.0), radius: 50.0);
canvas.drawArc(rect, 0, pi/2, false, _circlePaint);
学习到这里,简单基础的绘制基本上结束了,然后还有贝塞尔曲线的绘制,巴拉巴拉啥的,以后有空再去学习,毕竟数学学得也一般般~