Flutter开发者

自定义View【2】

2018-10-23

上期回顾

在前面的文章中我们学习了部分绘制的相关方法,在本篇文章中我们会继续再介绍一些常用的绘制方法。

绘制路径drawPath

drawPath(Path path, Paint paint)

绘制路径非常的简单,首先需要一个要绘制的路径path,然后就是这个paint了。

Path的用法也非常的简单,下面列出一下常用的方法:


方法名 作用
moveTo 将路径起始点移动到指定的位置
relativeMoveTo 相对于当前位置移动到
lineTo 从当前位置连接指定点
relativeLineTo 相对当前位置连接到
arcTo 二阶贝塞尔曲线
conicTo 三阶贝塞尔曲线
add** 添加其他图形,如addArc,在路径是添加圆弧
contains 路径上是否包括某点
transfor 给路径做matrix4变换
combine 结合两个路径
close 关闭路径,连接路径的起始点
reset 重置路径,恢复到默认状态

那么我们还是举个例子吧:

1
2
3
4
5
6
7

@override
void paint(Canvas canvas, Size size) {
Path path = new Path();
path.lineTo(100, 200);
canvas.drawPath(path, _paint);
}

当然,我们也可以绘制多个过程path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

@override
void paint(Canvas canvas, Size size) {
Path path = new Path();

path.moveTo(50, 50);
path.lineTo(160, 50);
path.lineTo(160, 160);
path.lineTo(50, 160);

path.moveTo(160, 105);
path.lineTo(50, 105);

canvas.drawPath(path, _paint);
}

当然我们也可以尝试画画其他的图形

使用arcTo绘制曲线,不熟悉贝塞尔曲线的童鞋可以自行google你科普下。

1
2
3
4
5
6
7

@override
void paint(Canvas canvas, Size size) {
Path path = new Path();
path.arcTo(Rect.fromCircle(center: Offset(100, 100),radius: 80),0,3.14,false);
canvas.drawPath(path, _paint);
}

使用二阶贝塞尔曲线绘制弧线

或者直接绘制一个圆

1
2
3
4
5
6
7

@override
void paint(Canvas canvas, Size size) {
Path path = new Path();
path.arcTo(Rect.fromCircle(center: Offset(100, 100),radius: 80),0,6.28,false);
canvas.drawPath(path, _paint);
}

当然我们也可以使用三阶贝塞尔曲线来绘制其他的图形:

比如,我对你们的爱哦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@override
void paint(Canvas canvas, Size size) {
Path path = new Path();

var width = 200;
var height = 300;
path.moveTo(width / 2, height / 4);
path.cubicTo((width * 6) / 7, height / 9, (width * 12) / 13,
(height * 2) / 5, width / 2, (height * 7) / 12);
canvas.drawPath(path, _paint);

Path path2 = new Path();
path2.moveTo(width / 2, height / 4);
path2.cubicTo(width / 7, height / 9, width / 13, (height * 2) / 5,
width / 2, (height * 7) / 12);
canvas.drawPath(path2, _paint);
}

绘制图片drawImage

drawImage(Image image, Offset p, Paint paint)

绘制起来也非常的简单,首先我们需要获取本地图片文件,然后绘制图片即可。

看个例子:

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
97
98
99
100
101
102
103
104

import 'dart:async';

import 'package:flutter/material.dart';
import 'dart:ui' as flutterui;

import 'package:flutter/rendering.dart' as ui;
import 'package:flutter/services.dart' as ui;
import 'package:flutter/widgets.dart' as ui;
import 'package:flutter/material.dart' as ui;
import 'package:flutter/painting.dart' as ui;

/// ------------------------------
/// ┌─┐┬ ┬ ┬┌─┐┬ ┬
/// ├┤ │ └┬┘│ ││ │
/// └ ┴─┘┴ └─┘└─┘
/// Author : fzl flyou
/// Date : 2018/10/12 0012
/// ProjectName : test1
/// Description :
/// Version : V1.0
/// ------------------------------

void main() {
runApp(new MaterialApp(
home: PainterDemo(),
));
}

class PainterDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return PainterDemoState();
}
}

class PainterDemoState extends State<PainterDemo> {
var image;

@override
void initState() {
super.initState();
ImageLoader.load("assets/icon.png").then((image) {
setState(() {
this.image = image;
});
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("PainterDemo"),
),
body: CustomPaint(
painter: CirclePainter(image),
),
);
}
}

class CirclePainter extends CustomPainter {
var image;

Paint _paint = new Paint()
..color = Colors.blueAccent
..strokeCap = StrokeCap.round
..isAntiAlias = true
..style = PaintingStyle.stroke
..strokeWidth = 5.0;

CirclePainter(this.image);

@override
void paint(Canvas canvas, Size size) {
canvas.drawImage(image, Offset(100.0, 100.0), _paint);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

class ImageLoader {
static ui.AssetBundle getAssetBundle() => (ui.rootBundle != null)
? ui.rootBundle
: new ui.NetworkAssetBundle(new Uri.directory(Uri.base.origin));

static Future<flutterui.Image> load(String url) async {
ui.ImageStream stream = new ui.AssetImage(url, bundle: getAssetBundle())
.resolve(ui.ImageConfiguration.empty);
Completer<flutterui.Image> completer = new Completer<flutterui.Image>();
void listener(ui.ImageInfo frame, bool synchronousCall) {
final flutterui.Image image = frame.image;
completer.complete(image);
stream.removeListener(listener);
}

stream.addListener(listener);
return completer.future;
}
}

当然,绘制picture与绘制image类似,大家可以自己在线尝试。

绘制颜色drawColor

绘制颜色用起来就比较简单了,主要是用来给你绘制过的图形上做颜色的变换,颜色的变换模式有多种,大家可以在下面自己尝试,下面仅仅演示下如何使用

1
2
3
4
5
6
7
8
9
10
11


@override
void paint(Canvas canvas, Size size) {

canvas.drawCircle(Offset(100, 100), 80.0, _paint);

// canvas.drawColor(Colors.red, BlendMode.color);


}

首先我们先绘制一个颜色为蓝色的圆

然后我们打开代码的注释,绘制红色

或者我们修改绘制的模式为

BlendMode.colorDodge

小伙伴们可以自己在下面尝试不同的颜色模式来看看效果。

小结

  • 使用drawPath绘制路径
  • 使用而塞尔曲线绘制想要的曲线效果
  • 使用drawImage来绘制图片
  • 使用drawColor来绘制颜色迭代效果
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章