【Flutter学习】之绘画实例(二)
一,画路径 - drawPath(Path path, Paint paint)
Path 主要有方法如下:
直接描述路径的方法还可以细分为两组:添加子图形和画线(直线或曲线)
addXXX() - 添加子图形(由于此类方法参数与上面介绍的画简单图形一样,就不多赘述了)
- addArc(Rect oval, double startAngle, double sweepAngle) - 添加圆弧
- addOval(Rect oval) - 添加圆
- addPolygon(List<Offset> points, bool close) - 添加一个由点的集合描述的多边形
- addRect(Rect rect) - 添加矩形
- addRRect(Rect rect) - 添加圆角矩形
- addPath(Path path, Offset offset) - 添加子路径
XXXTo() - 画线(直线或曲线)
这个方法通过描述路径的方式来绘制图形,用法大概是这样:
Path _path = Path();
@override
void paint(Canvas canvas, Size size) {
_paint.style = PaintingStyle.stroke; // 画线模式
_path.addArc(new Rect.fromLTWH(, , , ), 135.0 * (pi / 180.0), 225.0 * (pi / 180.0));
_path.addArc(new Rect.fromLTWH(, , , ), 180.0 * (pi / 180.0), 225.0 * (pi / 180.0));
_path.lineTo(, );
_path.lineTo(, );
canvas.drawPath(_path, _paint);
}

向目标位置画直线 - lineTo(double x, double y) / relativelineTo(double x, double y)
从当前位置向目标位置画一条直线, x 和 y 是目标位置的坐标。这两个方法的区 别是, lineTo(x, y) 的参数是绝对坐标,而 relativeLineTo(x, y) 的参数是相对当前位置的相对坐标 ;_paint.style = PaintingStyle.stroke; // 画线模式
_path.lineTo(, ); // 由当前位置 (0, 0) 向 (100, 100) 画一条直线
_path.relativeLineTo(, ); // 由当前位置 (100, 100) 向正右方画100像素的位置
canvas.drawPath(_path, _paint);

画二阶贝塞尔曲线 - quadraticBezierTo(double x1, double y1, double x2, double y2) / relativeQuadraticBezierTo(double x1, double y1, double x2, double y2)
x1,y1是控制点的坐标;x2,y2是结束点的坐标;relativeQuadraticBezierTo()同上面相对直线方法
_paint.style = PaintingStyle.stroke; // 画线模式
List<Offset> points = new List();
points.add(new Offset(, )); // 画出控制点位置,方便理解
canvas.drawPoints(PointMode.points, points, _paint);
_path.moveTo(, ); // 移动起点到(0,100)
_path.quadraticBezierTo(, , , );
canvas.drawPath(_path, _paint);
画三阶贝塞尔曲线 - cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) / relativeCubicTo(double x1, double y1, double x2, double y2, double x3, double y3)
和上面这个 quadraticBezierTo()和relativeQuadraticBezierTo() 的二阶贝塞尔曲线同理,就不多说了。
@override
void paint(Canvas canvas, Size size) { Path path = new Path()..moveTo(100.0, 100.0);
List<Offset> points = new List();
points.add(new Offset(, )); // 画出控制点位置,方便理解
canvas.drawPoints(PointMode.points, points, _paint);
path.moveTo(, ); // 移动起点到(0,100)
path.cubicTo(, , , , , );
canvas.drawPath(path, _paint);
}
移动到某点 - moveTo(double x, double y) / relativeMoveTo(double dx, double dy)
不论是直线还是贝塞尔曲线,都是以当前位置作为起点,而不能指定起点。但可以通过 moveTo(x, y) 或 relativeMoveTo(x, y) 来改变当前位置,从而间接地设置这些方法的起点。
_paint.style = PaintingStyle.stroke; // 画线模式
_path.moveTo(, ); // 移动起点到(20,40)
_path.lineTo(, ); // 画条斜线
_path.moveTo(, ); // 移动起点到(100,20)
_path.lineTo(, ); // 画条直线
canvas.drawPath(_path, _paint);但凡事都有例外 arcTo() 这个方法并不从当前位置开始绘制

画弧线 - arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)
前三个参数,我们已经很熟悉了,最后一个参数的意思是,画这个弧的时候是拖着笔到起点还是抬下笔到起点
_paint.style = PaintingStyle.stroke; // 画线模式
_path.moveTo(, ); // 移动起点到(20,40)
_path.lineTo(, ); // 画条斜线
_path.arcTo(new Rect.fromLTWH(, , , ), 0.0 * (pi / 180.0), 90.0 * (pi / 180.0), false);
canvas.drawPath(_path, _paint);拖着笔:

抬下笔:

封闭当前路径 - close()
_paint.style = PaintingStyle.stroke; // 画线模式
_path.moveTo(, ); // 移动起点到(20,20)
_path.lineTo(, ); // 画条斜线
_path.arcTo(new Rect.fromLTWH(, , , ), 0.0 * (pi / 180.0), 90.0 * (pi / 180.0), false);
_path.close(); // 封闭当前路径
canvas.drawPath(_path, _paint);
到这里Canvas图形的绘制就讲的差不多了,图形简单时,使用 drawCircle() drawRect() 等方法来直接绘制;图形复杂时,使用 drawPath() 来绘制自定义图形。 除此之外, Canvas 还可以绘制图片和文字。
二,画图片 - drawImage(Image image, Offset p, Paint paint) / drawImageRect(Image image, Rect src, Rect dst, Paint paint)
系统方法
drawImage() 从指定点开始将图片宽高按像素绘制,由于无法控制图片的大小,并不常用;第一个参数是ui包下的Image,并不是Image Widge
使用方法
Image 可以通过以下代码获取
ui.Image image;
/**
* 初始化图片
*
Future<VoidCallback> initImage() async {
image = await _loadImage("./assets/images/img.jpg");
return null;
} /**
* 通过assets路径,获取资源图片
*/
Future<Image> _loadImage(String assets) async {
final ByteData data = await rootBundle.load(assets);
if (data == null) throw 'Unable to read data';
Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
FrameInfo frame = await codec.getNextFrame();
return frame.image;
}然后在initState() 方法中初始化( shouldRepaint() 方法一定要记得返回 true ,否则无法重绘)
void initState() {
super.initState();
painter.initImage().then((val) {
setState(() {
});
});
}最后在 paint() 方法中填入以下代码:
canvas.drawImage(image, new Offset(, ), _paint);
drawImageRect() 这个方法经常使用;主要了解第二个参数与第三个参数:
- Rect src - 原图的区域,一般传图片的宽高
- Rect dst - 显示的区域, 指图片显示的区域,如果原图区域宽高比与显示区域不一致,原图会被拉伸或压缩
canvas.drawImageRect(image, Offset(0.0, 0.0) & Size(image.width.toDouble(), image.height.toDouble()), Offset(0.0, 0.0) & Size(200, 200), _paint);正常比例:

拉伸:

三,画文字 - drawParagraph(Paragraph paragraph, Offset offset)
系统方法
drawParagraph(Paragraph paragraph, Offset offset)
使用方法
代码注释的很清楚,这里循环画了5段文字
for (int i = ; i< ;i++){
// 新建一个段落建造器,然后将文字基本信息填入;
ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
textAlign: TextAlign.left,
fontWeight: FontWeight.w300,
fontStyle: FontStyle.normal,
fontSize: 15.0+i,
));
pb.pushStyle(ui.TextStyle(color: Colors.black87));
pb.addText('Flutter一统移动端');
// 设置文本的宽度约束
ParagraphConstraints pc = ParagraphConstraints(width: );
// 这里需要先layout,将宽度约束填入,否则无法绘制
Paragraph paragraph = pb.build()..layout(pc);
// 文字左上角起始点
Offset offset = Offset(, +i*40.0);
canvas.drawParagraph(paragraph, offset);
}示例

参考:https://juejin.im/post/5c67a6a0f265da2dae510fa2#heading-14
【Flutter学习】之绘画实例(二)的更多相关文章
- Android JNI和NDK学习(09)--JNI实例二 传递类对象
1 应用层代码 NdkParam.java是JNI函数的调用类,它的代码如下: package com.skywang.ndk; import android.app.Activity; impo ...
- 【Flutter学习】页面布局之其它布局处理
一,概述 Flutter中拥有30多种预定义的布局widget,常用的有Container.Padding.Center.Flex.Row.Colum.ListView.GridView.按照< ...
- 一起学习造轮子(二):从零开始写一个Redux
本文是一起学习造轮子系列的第二篇,本篇我们将从零开始写一个小巧完整的Redux,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Promises/A+,Red ...
- Linux学习之CentOS(十二)--crontab命令的使用方法
http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/06/3002602.html crontab命令常见于Unix和Linux的操作系统之 ...
- Flutter学习笔记与整合
1.Dart 面向对象语言,与java类比学习 非常适合移动和Web应用程序 1.dart官网 2.Dark2 中文文档 3.Dart语法学习 4.极客学院Dart学习 5.Flutter与Dart ...
- WCF入门教程(四)通过Host代码方式来承载服务 一个WCF使用TCP协议进行通协的例子 jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding System.ServiceModel.WSHttpBinding协议 学习WCF笔记之二 无废话WCF入门教程一[什么是WCF]
WCF入门教程(四)通过Host代码方式来承载服务 Posted on 2014-05-15 13:03 停留的风 阅读(7681) 评论(0) 编辑 收藏 WCF入门教程(四)通过Host代码方式来 ...
- Flutter学习笔记(3)--Dart变量与基本数据类型
一.变量 在Dart里面,变量的声明使用var.Object或Dynamic关键字,如下所示: var name = ‘张三’: 在Dart语言里一切皆为对象,所以如果没有将变量初始化,那么它的默认值 ...
- Flutter学习笔记(4)--Dart函数
如需转载,请注明出处:Flutter学习笔记(4)--Dart函数 Dart是一个面向对象的语言,所以函数也是对象,函数属于Function对象,函数可以像参数一样传递给其他函数,这样便于做回调处理: ...
- Flutter学习笔记(5)--Dart运算符
如需转载,请注明出处:Flutter学习笔记(5)--Dart运算符 先给出一个Dart运算符表,接下来在逐个解释和使用.如下: 描述 ...
随机推荐
- Python3解leetcode Binary Tree PathsAdd DigitsMove Zeroes
问题描述: Given an array nums, write a function to move all 0's to the end of it while maintaining the r ...
- 4412 chmod权限
chmod权限 使用命令"man 2 chmod"学习chmod函数• int chmod(const char *path, mode_t mode);– 参数*path:文件路 ...
- python 收集测试日志--格式
Python的logging模块提供了通用的日志系统,这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现方式记录 ...
- Go的struct
1. 前言 Go的struct声明允许字段附带Tag来对字段做一些标记. 该Tag不仅仅是一个字符串那么简单,因为其主要用于反射场景,reflect包中提供了操作Tag的方法,所以Tag写法也要遵循一 ...
- Modular arithmetic and Montgomery form 实现快速模乘
题目: 电音之王 题解: 求数列前n项相乘并取模 思路: ①.这题的乘法是爆long long的,可以通过快速幂的思想去解决(按数位对其中的一个数进行剖分).当然你的乘法会多出一个log的复杂度... ...
- linux 修改系统字符集,查看字符
修改系统字符集 # cd /etc/sysconfig # vi i18n -------------------文件内容------------------ LANG="zh_CN.GB1 ...
- Asp.Net Core 第02局:Program
总目录 前言 本文介绍Program,它包含程序的入口Main方法.从这里开始... 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 第一手:Program ...
- ubuntu+qt+opencv
linux下Qt+OpenCv环境的搭建: https://blog.csdn.net/yaowangII/article/details/84303124 1.qt:https://blog.csd ...
- oo前三次作业博客总结
第一次作业 实现多项式的加减运算,主要问题是解决输入格式的判断问题. 输入实例: {(3,0), (2,2), (12,3)} + {(3,1), (-5,3)} – {(-199,2), (29,3 ...
- SQLServer2008不允许保存更改
sql server 2008在更改表结构的时候提示 “不允许保存更改,您所做的更改要求删除并重新创建以下表” 解决方案: 1.一般情况下:工具--选项--Designers--表设计器和数据库设计器 ...