小菜前几天整理了以下 Canvas 的部分方法,今天小菜继续学习 Canvas 第二部分。

drawXXX

drawShadow 绘制阴影

drawShadow 用于绘制阴影,第一个参数时绘制一个图形 Path,第二个是设置阴影颜色,第三个为阴影范围,最后一个阴影范围是否填充满;

canvas.drawShadow(
Path()
..moveTo(30.0, 30.0)..lineTo(120.0, 30.0)
..lineTo(120.0, 60.0)..lineTo(30.0, 60.0)
..close(),
Colors.blue, 3, false);
canvas.drawShadow(
Path()
..moveTo(30.0, 90.0)..lineTo(120.0, 90.0)
..lineTo(120.0, 120.0)..lineTo(30.0, 120.0),
Colors.blue, 10, false);
canvas.drawShadow(
Path()
..moveTo(30.0, 150.0)..lineTo(120.0, 150.0)
..lineTo(120.0, 180.0)..lineTo(30.0, 180.0)
..close(),
Colors.blue, 3, true);
canvas.drawPath(
Path()
..moveTo(30.0, 210.0)..lineTo(120.0, 210.0)
..lineTo(120.0, 240.0)..lineTo(30.0, 240.0),
Paint()..color = Colors.blue..strokeWidth = 2..style = PaintingStyle.stroke);

drawImage 绘制图片

drawImage 用于绘制图片,绘制图片是重点,此时的 Image 并非日常所用的图片加载,而是用的 dart.ui 类中的 ui.Image 并转换成字节流 ImageStream 方式传递,包括本地图片或网络图片

// 获取图片 本地为false 网络为true
Future<ui.Image> _loadImage(var path, bool isUrl) async {
ImageStream stream;
if (isUrl) {
stream = NetworkImage(path).resolve(ImageConfiguration.empty);
} else {
stream =
AssetImage(path, bundle: rootBundle).resolve(ImageConfiguration.empty);
}
Completer<ui.Image> completer = Completer<ui.Image>();
void listener(ImageInfo frame, bool synchronousCall) {
final ui.Image image = frame.image;
completer.complete(image);
stream.removeListener(listener);
} stream.addListener(listener);
return completer.future;
} // 加载图片
_prepareImg() {
_loadImage('images/icon_hzw02.jpg', false).then((image1) {
_image1 = image1;
}).whenComplete(() {
_loadImage('https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=703702342,1604162245&fm=26&gp=0.jpg', true)
.then((image2) {
_image2 = image2;
}).whenComplete(() {
_prepDone = true;
if (this.mounted) {
setState(() {});
}
});
});
} canvas.drawImage(this.image, ui.Offset(120.0, 540.0), Paint());
canvas.drawImage(this.image2, ui.Offset(60.0, 60.0), Paint());

Tips:

小菜在尝试过程中总是加载失败,后来理解为绘制过程需要时间,可以通过 setState(() {});whenComplete 判断状态后进行刷新,这种方式并非最佳,希望有更好方式的朋友多指导。

drawImageRect 绘制矩形图片

drawImageRect 除了可以正常绘制图片之外,还可以绘制图片部分内容,如下:第一个参数为 ui.Image,第二个参数为需要原图绘制矩形范围,第三个参数为本次绘制矩形范围,最后一个为画笔;

小菜绘制原图与部分图进行对比,drawImageRect 绘制的原图粉色圈出的范围;且 drawImageRect 效率更好,推荐使用;

canvas.drawImage(this.image, ui.Offset(60.0, 540.0), Paint());
canvas.drawImageRect(
this.image,
Rect.fromLTWH(0, 0, 60, 60),
Rect.fromLTWH(60, 60, image.width.toDouble(), image.height.toDouble()),
Paint());

drawImageNine 绘制九图

drawImageNine 同样用来绘制图片,与原图绘制方式不同在于,drawImageNine 中第二个参数矩形变长延伸将原图分割为九部分,划为中心区域,第三个参数矩形即绘制整体矩形范围,包括四个顶点位置;小菜绘制原图与部分图进行对比,drawImageNine 绘制的原图绿色圈出的范围,小菜感觉类似于裁剪了原图;

canvas.drawImage(this.image, ui.Offset(60.0, 540.0), Paint());
canvas.drawImageNine(
this.image,
Rect.fromLTWH(0, 0, 120, 60),
Rect.fromLTWH(
60, 1020, image.width.toDouble() - 120, image.height.toDouble()),
Paint());

drawParagraph 绘制文字段落

小菜以前认为 Canvas 不支持绘制文字,现在学习了 drawParagraph 完全可以绘制文字效果与 TextPainter 效果相同;

文字段落 Paragraphdart.ui 中的类,用构造器方式进行内容绑定;ParagraphStyle 用来设置文字的样式属性,包括文字位置/方向/字体粗细/文字样式/行数等;其中 ellipsis 用来设置内容超出范围截取时最后展示内容,可随意编辑;

ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
textAlign: TextAlign.center,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
fontSize: 18,
))
..pushStyle(ui.TextStyle(color: Colors.blue))
..addText(
'Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。');
ParagraphConstraints pc = ParagraphConstraints(width: Screen.width - 60);
Paragraph paragraph = pb.build()..layout(pc);
canvas.drawParagraph(paragraph, Offset(30, 30)); pb = ParagraphBuilder(ParagraphStyle(
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w300,
fontSize: 18,
))
..pushStyle(ui.TextStyle(color: Colors.red))
..addText(
'Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。');
pc = ParagraphConstraints(width: Screen.width - 60);
paragraph = pb.build()..layout(pc);
canvas.drawParagraph(paragraph, Offset(30, 180)); pb = ParagraphBuilder(ParagraphStyle(
fontStyle: FontStyle.normal,
fontSize: 18,
maxLines: 3,
ellipsis: '...',
))
..pushStyle(ui.TextStyle(color: Colors.green))
..addText(
'Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。');
pc = ParagraphConstraints(width: Screen.width - 60);
paragraph = pb.build()..layout(pc);
canvas.drawParagraph(paragraph, Offset(30, 340));

clipXXX

以上介绍的都是绘制方法,接下来小菜简单介绍几种裁剪方法。

clipRect 裁剪矩形

clipRect 可以在规定的矩形内进行绘制,超出范围不绘制;

canvas.clipRect(Rect.fromLTWH(30, 1200, Screen.width / 0.3 - 60, 300),
doAntiAlias: false);
canvas.drawImage(this.image, ui.Offset(260, 1200), Paint());

clipRRect 裁剪圆角矩形

clipRRect 可以在规定的圆角矩形内进行绘制,超出范围不绘制;

canvas.clipRRect(
RRect.fromRectXY(
Rect.fromLTWH(300, 1600, image.width - 60.0, 300), 20, 20),
doAntiAlias: false);
canvas.drawImage(this.image, ui.Offset(260, 1200), Paint());

clipPath 裁剪由线围成区域

clipPath 可以在规定的点连线范围内进行绘制,默认终点与始点连接,当然可以绘制圆或贝塞尔曲线等,超出范围不绘制;

canvas.clipPath(Path()
..moveTo(300, 100)..lineTo(900, 100)
..lineTo(800, 600)..lineTo(400, 600));
canvas.drawImage(this.image, ui.Offset(260, 90), Paint());


Canvas 真的非常强大,还有很多研究不透彻的地方,小菜还在不断学习,有错误的地方烦请多多指点!

Flutter 35: 图解自定义 View 之 Canvas (二)的更多相关文章

  1. Flutter 34: 图解自定义 View 之 Canvas (一)

    小菜最近在学习自定义 View,刚了解了一下 Paint 画笔的神奇之处,现在学习一下 Canvas 画布的神秘之处.Flutter 提供了众多的绘制方法,小菜接触不深,尽量都尝试一下. Canvas ...

  2. Flutter 36: 图解自定义 View 之 Canvas (三)

    小菜继续学习 Canvas 的相关方法: drawVertices 绘制顶点 小菜上次没有整理 drawVertices 的绘制方法,这次补上:Vertice 即顶点,通过绘制多个顶点,在进行连线,多 ...

  3. 安卓自定义View进阶-Canvas之画布操作 转载

    安卓自定义View进阶-Canvas之画布操作 转载 https://www.gcssloop.com/customview/Canvas_Convert 本来想把画布操作放到后面部分的,但是发现很多 ...

  4. Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解

    上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas和Paint,从细节上更进一步的讲解自定 ...

  5. Android自定义View学习(二)

    绘制顺序 参考:HenCoder Android 开发进阶:自定义 View 1-5 绘制顺序 绘制过程 包括 背景 主体(onDraw()) 子 View(dispatchDraw()) 滑动边缘渐 ...

  6. Android进阶之绘制-自定义View完全掌握(二)

    这是自定义View系列的第二篇博客,我们继续来学习关于自定义View的知识. 今天我们来实现一下广告条案例. 我们要实现的是这样的一个效果. 要想实现这样的效果,我们可以借助ViewPager控件,然 ...

  7. 自定义View之Canvas使用

    自定义View的绘制流程一般都是这样:提前创建好Paint对象,重写onDraw(),把绘制代码卸载ondraw()里面,大致如下: Paint paint = new Paint(); @Overr ...

  8. Android 自定义View 三板斧之二——组合现有控件

    通常情况下,Android实现自定义控件无非三种方式. Ⅰ.继承现有控件,对其控件的功能进行拓展. Ⅱ.将现有控件进行组合,实现功能更加强大控件. Ⅲ.重写View实现全新的控件 上文说过了如何继承现 ...

  9. 自定义View(4)Canvas和Paint常用绘制函数

    画布Canvas 在Android下进行2D绘图需要Canvas类的支持,它位于"android.graphics.Canvas"包下,直译过来为画布的意思,用于完成在View上的 ...

随机推荐

  1. 微信自定义分享 IOS端分享失败

    1.在IOS微信浏览器中自定义分享link 链接中的中文需要encodeURIComponent() 编码(安卓会自动编码) 2.另外在IOS微信浏览器中自定义分享 imgUrl  不能大于34KB ...

  2. 001-log-log体系-log4j、jul、jcl、slf4j,日志乱象的归纳与统一

    一.概述 log4j→jul→jcl→slf4j之后就开始百花齐放[slf4j适配兼容新老用户] 1.1.log4j阶段 在JDK出现后,到JDK1.4之前,常用的日志框架是apache的log4j. ...

  3. 阶段5 3.微服务项目【学成在线】_day04 页面静态化_13-页面静态化-数据模型-轮播图DataUrl接口

    要开发轮播图的DataUrl的接口 轮播图的配置的集合 xc-framework-model这个module下 CmsConfigModel的类的属性 定义接口 在api里面定义接口:CmsConfi ...

  4. 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_11-修改页面-前端-Api调用

    修改数据 这是提交按钮的事件editSubmit 注意修改的方法是put方法.所以用requestPut 操作成功自动返回 测试 成功后自动跳转到列表页 修改后的数据

  5. Python字符串逐字符或逐词反转方法

    Python字符串逐字符或逐词反转方法 这篇文章主要介绍了Python字符串逐字符或逐词反转方法,本文对逐字符或逐词分别给出两种方法,需要的朋友可以参考下 目的 把字符串逐字符或逐词反转过来,这个蛮有 ...

  6. sql语句 两表关联查询计算数量

    select sum(a1.`num`)   from `order_orderlistrow` as a1 INNER JOIN `order_orderlist` as a2 on a1.`ord ...

  7. React Native 中 component 生命周期

    React Native 中 component 生命周期 转自 csdn 子墨博客  http://blog.csdn.net/ElinaVampire/article/details/518136 ...

  8. java类和对象详解

    类和对象 java 是面向对象的语言 即 万物皆对象c语言是面向过程语言 一.怎么去描述一个对象? (1)..静态的(短时间内不会改变的东西) 例如:外观,颜色,品牌 (2).动态的(动作) 可以干什 ...

  9. 更新neo4j节点信息

    将多个属性的内容更新到节点上 def update_by_id(id,graph,**kwargs): """ 更新节点的属性 根据节点的ID来更新节点的属性,如果存在该 ...

  10. 图片水印工具类java

    关于jar包的导入我就不多说了,我会把引入的jar包显示出来,大家自行Google package com.net.util; import java.awt.AlphaComposite; impo ...