自定义View项目实战(一):Canvas与Paint基础
本文重点
着重介绍自绘控件,因为所有的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
imagevoid 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
imagevoid 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 画笔
示例:
imagevoid 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
imagevoid 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
示例:
imagevoid 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;
imagevoid 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;
imagevoid 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()
imagevoid 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);
}