Flutter学习:使用CustomPaint绘制路径

Flutter学习:认识CustomPaint组件和Paint对象

Flutter学习:使用CustomPaint绘制路径

Flutter学习:使用CustomPaint绘制图形

Flutter学习:使用CustomPaint绘制文字

Flutter学习:使用CustomPaint绘制图片

drawPath 绘制路径

drawPath需要传递2个参数:

  • Path path 路径对象
  • Paint paint 绘制对象
 

dart

复制代码

Path path = Path()..moveTo(100, 100); path.lineTo(250, 250); path.lineTo(350, 180); path.lineTo(200, 500); // 控制路径是否闭合,可不写 path.close(); canvas.drawPath(path, paint);

image

path.moveTo和path.lineTo

path.moveTopath.lineTo一样,都需要传递2个参数:

  • double x用来设置点的横坐标(x轴)
  • double y用来设置点的纵坐标(y轴)
 

dart

复制代码

path.moveTo(80, 200); path.lineTo(320, 400); canvas.drawPath(path, paint);

其中p0path.moveTo设置的坐标,p1path.lineTo设置的坐标

image

path.relativeMoveTo和path.relativeLineTo

path.relativeMoveTopath.relativeLineTofiType的使用方法和path.moveTopath.lineTo一样,只是起始点不再是左上角,而是前一个点的坐标

path.close

用来设置路径是否自己闭合:

 

dart

复制代码

path.close();

image

path.reset

清除之前所有的Path对象。并重置原点为左上角。

 

dart

复制代码

path.reset();

path.fillType

关于fillType的资料可以查看以下文章:

  • Quartz2D的渲染模式

fillType有两个枚举值:

  • PathFillType.nonZero:内部由有符号边缘交叉的非零和定义。对于给定点,如果从该点到无穷远的线与绕该点顺时针方向的线交叉的次数与与绕该点逆时针方向的线交叉的次数不同,则认为该点位于路径的内侧。
  • PathFillType.evenOdd:内部由奇数个边缘交叉定义。对于给定点,如果从该点到无穷远的线穿过奇数条线,则认为该点位于路径的内侧
 

dart

复制代码

Path path = Path()..moveTo(size.width / 2, 200); path.lineTo(size.width / 4, 500); path.lineTo(size.width / 7 * 6, 320); path.lineTo(size.width / 7, 320); path.lineTo(size.width / 4 * 3, 500); path.close(); // 默认值 path.fillType = PathFillType.nonZero; path.fillType = PathFillType.evenOdd; canvas.drawPath(path, paint);

image

path.addArc

通过路径绘制圆弧

addArc(Rect oval, double startAngle, double sweepAngle)需要传递3个参数:

  • oval绘制一个矩形
  • startAngle圆弧开始处
  • sweepAngle圆弧开始到结束的角度大小
 

dart

复制代码

// 只有path.addArc方法,path.moveTo方法将会无效 Path path = Path(); // path.moveTo(size.width / 2, 200); 无效 Rect oval = Rect.fromPoints(const Offset(80, 80), const Offset(300, 180)); path.addArc(oval, 0, 4); canvas.drawPath(path, paint);

 

dart

复制代码

// 有path.moveTo、path.lineTo、path.addArc这3个方法 // path.lineTo在谁的后面就跟谁连接,默认path.moveTo为(0,0) Path path = Path(); path.moveTo(size.width / 2, 200); Rect oval = Rect.fromPoints(const Offset(80, 80), const Offset(300, 180)); path.addArc(oval, 0, 4); path.lineTo(250, 400); canvas.drawPath(path, paint);

image

path.addOval、path.addRect、path.addRRect用法和path.addArc一样

path.addPath

该方法将复制一遍已绘制的路径,并进行偏移

addPath(Path path, Offset offset, {Float64List? matrix4})可以传递3个参数,2个必要的,一个可选的:

  • path已绘制的路径对象
  • offsetpath对象进行的偏移量
  • matrix4将矩阵平移给定偏移量

没有使用matrix4属性:

 

dart

复制代码

Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); path.addPath(path, const Offset(120, 120)); canvas.drawPath(path, paint);

使用了matrix4属性:

 

dart

复制代码

Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); // 变形(倾斜)路径 path.addPath(path, const Offset(120, 120), matrix4: Matrix4.skew(.1, .1).storage); canvas.drawPath(path, paint);

image

path.extendWithPath

效果和path.addPath一样,属性也一样,只是该方法会将这两条线段连接起来:

 

dart

复制代码

Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); path.extendWithPath(path, const Offset(120, 120), matrix4: Matrix4.skew(.2, .4).storage); canvas.drawPath(path, paint);

image

path.addPolygon

添加一条新路径

addPolygon(List points, bool close)需要传递2个参数:

  • points一系列点的坐标
  • close是否首位相连
 

dart

复制代码

path.moveTo(size.width / 2, 200); path.lineTo(200, 380); path.lineTo(80, 460); List<Offset> points = const [ Offset(100, 40), Offset(350, 240), Offset(200, 500), ]; path.addPolygon(points, true); canvas.drawPath(path, paint);

image

path.arcTo

绘制圆弧路径

arcTo( Rect rect, double startAngle, double sweepAngle, bool forceMoveTo, )需要传递4个参数:

  • rect绘制一个矩形用来确定圆弧的位置
  • startAngle圆弧开始的角度
  • sweepAngle圆弧开始到结束的角度大小
  • forceMoveTo圆弧路径为新路径还是与原路径相连
 

dart

复制代码

path.moveTo(size.width / 2, 200); path.lineTo(80, 460); Rect rect = Rect.fromPoints(const Offset(80, 340), const Offset(280, 420)); // forceMoveTo为true path.arcTo(rect, 0, 5, true); // forceMoveTo为false path.arcTo(rect, 0, 5, false); canvas.drawPath(path, paint);

image

path.arcToPoint

绘制一个两点之间线段距离的直径圆弧

arcToPoint(Offset arcEnd, {Radius radius = Radius.zero, double rotation = 0.0, bool largeArc = false, bool clockwise = true})可以传递5个参数,1个必要的,4个可选的:

  • arcEnd确定圆弧的结束点坐标
  • radius为0时将绘制一条直线
  • rotation感觉没啥用
  • largeArc是否是大圆弧
  • clockwise决定圆弧的绘制是从左边还是右边
 

dart

复制代码

path.moveTo(100, 200); // p0 path.arcToPoint( const Offset(320, 500), radius: const Radius.circular(.5), rotation: 2, argeArc: true, clockwise: false, ); // p1 path.arcToPoint( onst Offset(160, 250), adius: const Radius.circular(1), otation: 0, argeArc: true, lockwise: false, ); // p2 path.arcToPoint( const Offset(240, 375), radius: const Radius.circular(0), rotation: 5, largeArc: false, clockwise: true, ); canvas.drawPath(path, paint);

image

path.relativeArcToPoint

效果和path.arcToPoint一样,只是起始点为前一个点

path.conicTo

绘制圆锥路径

conicTo(double x1, double y1, double x2, double y2, double w)需要传递5个参数:

  • x1是第一个点x轴的坐标
  • y1是第一个点y轴的坐标
  • x2是第二个点x轴的坐标
  • y2是第二个点y轴的坐标
  • w是权重值。如果权重大于1,则曲线为双曲线;如果权重等于 1,则为抛物线;如果小于 1,则为椭圆
 

dart

复制代码

path.moveTo(size.width / 2, 200); // 权重=0 path.conicTo(80, 280, 300, 380, 0); // 权重=1 path.conicTo(80, 280, 300, 380, 1); // 权重=2 path.conicTo(80, 280, 300, 380, 2); canvas.drawPath(path, paint);

image

path.relativeConicTo

效果和path.conicTo一样,只是起始点为前一个点

path.quadraticBezierTo

使用控制点 (x1,y1) 添加一个从当前点弯曲到给定点 (x2,y2) 的二次贝塞尔曲线段

quadraticBezierTo( double x1, double y1, double x2, double y2)需要传递4个参数:

  • x1是第一个点x轴的坐标
  • y1是第一个点y轴的坐标
  • x2是第二个点x轴的坐标
  • y2是第二个点y轴的坐标
 

dart

复制代码

path.moveTo(20, 200); path.quadraticBezierTo(200, 80, size.width - 20, size.width); canvas.drawPath(path, paint);

其中p0代表起始点位置(path.moveTo(20, 200)),p1的坐标是**(x1, y1)p2的坐标是(x2, y2)**

image

path.relativeQuadraticBezierTo

效果和path.quadraticBezierTo一样,只是起始点为前一个点

path.cubicTo

使用控制点 (x1,y1) 和 (x2,y2) 添加从当前点弯曲到给定点 (x3,y3) 的三次贝塞尔曲线段

cubicTo( double x1, double y1, double x2, double y2, double x3, double y3)需要传递6个参数:

  • x1是第一个点x轴的坐标
  • y1是第一个点y轴的坐标
  • x2是第二个点x轴的坐标
  • y2是第二个点y轴的坐标
  • x3是第三个点x轴的坐标
  • y3是第三个点y轴的坐标
 

dart

复制代码

path.moveTo(100, 200); path.cubicTo(120, 120, 240, 360, 310, 360); canvas.drawPath(path, paint);

其中p1代表p0点控制线的右边坐标,p2代表p3点控制线的左边坐标

image

path.relativeCubicTo

效果和path.cubicTo一样,只是起始点为前一个点

path.transform

复制线段,并对其路径进行变形。transform(Float64List matrix4)需要传递一个Float64List对象:

绘制第一条线段:

 

dart

复制代码

Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(80, 100); path.lineTo(140, 200); path.lineTo(320, 280); path.lineTo(100, 400); canvas.drawPath(path, paint);

绘制第二条线段:

 

dart

复制代码

Paint paint1 = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.blue; Path path1 = path.transform(Matrix4.skew(.1, .4).storage); canvas.drawPath(path1, paint1);

image

path.getBounds

获取路径的边界矩形

 

dart

复制代码

path.moveTo(50, 200); path.lineTo(300, 280); // path.getBounds()的结果为Rect.fromLTRB(50.0, 200.0, 300.0, 280.0) print(path.getBounds()); canvas.drawPath(path, paint);

image

path.shift

功能和path.add一样,只不过不会自动绘制一份路径,会把路径复制一份然后赋值给其他路径。

  • Offset offset,复制一份路径后设置偏移量

第一条路径:

 

dart

复制代码

Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(size.width / 2, 200); path.lineTo(80, 450); path.lineTo(size.width - 80, 450); path.close(); canvas.drawPath(path, paint);

复制第一条路径,并偏移:

 

dart

复制代码

Paint paint1 = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.blue; Path path1 = path.shift(const Offset(50, 50)); canvas.drawPath(path1, paint1);

image

path.contains

测试给定点是否在路径内。也就是说,如果路径与Canvas.clipPath一起使用,该点是否位于路径的可见部分。

  • Offset point,设置要检测的点的位置
 

dart

复制代码

Offset point1 = const Offset(200, 320); print(path.contains(point1)); Offset point2 = const Offset(200, 520); print(path.contains(point2));

如果该点在路径内,就返回 true,否则返回 false。

image

path.computeMetrics

path.computeMetrics可以获取路径的详细信息。

computeMetrics({bool forceClosed = false})有一个可选参数:

  • forceClosed,如果没有使用path.close();,该方法获取的结果isClose将会为false。设置该值为trueisClose将会为true

我们先绘制一条普通路径:

 

dart

复制代码

Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(size.width / 2, 200); path.lineTo(80, 450); path.lineTo(size.width - 80, 450); path.close();

如果直接对以上绘制的路径使用path.computeMetrics,会返回一个PathMetrics对象:

 

dart

复制代码

PathMetrics pathMetrics = path.computeMetrics();

一般我们需要用到的是PathMetric对象,获取该对象一共有以下几种方法:

 

dart

复制代码

// 如果只有一个PathMetric对象推荐使用该方法 PathMetric pathMetric = pathMetrics.single; // 如果有很多个PathMetric对象使用以下任意方法 PathMetric pathMetric = pathMetrics.elementAt(0); PathMetric pathMetric = pathMetrics.first; PathMetric pathMetric = pathMetrics.last;

获取到PathMetric对象后,我们就可以沿着这条路径绘制一条新的路径,使用extractPath方法。

该方法可以传递3个参数:

  • double start:给定线段开始的距离
  • double end:给定线段结束的距离
  • bool startWithMoveTo:是否以 moveTo 点开始绘制线段
 

dart

复制代码

Path path1 = pathMetric.extractPath(50, 400, startWithMoveTo: true);

 

dart

复制代码

Path path1 = pathMetric.extractPath(50, 400, startWithMoveTo: false);

image

关于computeMetrics的方法和属性还有很多没讲到,等以后有时间了再慢慢研究。

作者:菠萝橙子丶
链接:https://juejin.cn/post/7083304661645541390
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/123581.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

矢量绘图软件Sketch 99 for mac

Sketch是一款为用户提供设计和创建数字界面的矢量编辑工具。它主要用于UI/UX设计师、产品经理和开发人员&#xff0c;帮助他们快速设计和原型各种应用程序和网站。 Sketch具有简洁直观的界面&#xff0c;以及丰富的功能集&#xff0c;使得用户可以轻松地创建、编辑和共享精美的…

C++ vector 动态数组的指定元素删除

文本旨在对 C 的容器 vector 进行肤浅的分析。 文章目录 Ⅰ、vector 的指定元素删除代码结果与分析 Ⅱ、vector 在新增元素后再删除指定元素代码结果与分析 Ⅲ、vector 在特定条件下新增元素代码结果与分析 参考文献 Ⅰ、vector 的指定元素删除 代码 #include <iostream&g…

Python语言:经典例题分析讲解

题1&#xff1a; 通过观察我们可以得出以下结论&#xff1a; 代码实现&#xff1a; """ &#xff08;3&#xff09;输入整数n&#xff0c;输出n行的字符图案。如n5时输出以下图案&#xff1a;* *** ***** ******* *********""""" for…

河南开放大学与电大搜题微信公众号:携手共进,助力学习之路

作为河南省内颇具影响力和声誉的高等教育机构之一&#xff0c;河南开放大学一直致力于提供优质的教育资源和灵活的学习方式&#xff0c;以满足广大学习者的需求。而在这个追求知识的时代&#xff0c;学习者们尤其需要一个便捷、高效的工具来辅助学习。电大搜题微信公众号应运而…

python编程复习系列——week2(Input Output (2))

文章目录 一、多行代码语句二、Escape序列三、字符串格式四、数值运算课后作业 一、多行代码语句 &#x1f95e;使用反斜杠\来表示在下一行中继续使用一条语句。 subject_code "CSCI111" subject_mark 80 subject_grade "D" result "Subject re…

软件测试|黑盒测试方法论-判定表

在因果图分析法中最后会得出一个判定表&#xff0c;可以看出因果图和判定表是有联系的&#xff0c;一般需要结合起来使用。 因果图是一种分析工具&#xff0c;通过分析最终得到判定表&#xff0c;再通过判定表编写测试用例。在一定情况下也可以直接书写判定表&#xff0c;省略…

使用eXplorer本地搭建免费在线文件管理器并实现远程登录——“cpolar内网穿透”

文章目录 1. 前言2. eXtplorer网站搭建2.1 eXtplorer下载和安装2.2 eXtplorer网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1. 前言 通过互联网传输文件&#xff0c;是互联网最重要的应用之一&#xff0c;无论是…

Docker 学习路线 13:部署容器

部署容器是使用Docker和容器化管理应用程序更高效、易于扩展和确保跨环境一致性性能的关键步骤。本主题将为您概述如何部署Docker容器以创建和运行应用程序。 概述 Docker容器是轻量级、可移植且自我包含的环境&#xff0c;可以运行应用程序及其依赖项。部署容器涉及启动、管…

设计模式之生产者/消费者模式

文章目录 1. 简介2. 代码实现 1. 简介 生产者消费者模式与保护性暂停模式的GuardObject不同&#xff0c;它不需要产生结果和消费结果的线程一一对应。它使用一个消息队列来平衡生产者和消费者的线程资源。其中生产者仅负责产生结果数据&#xff0c;不关心数据该如何处理&#…

【算法与数据结构】17、LeetCode电话号码的字母组合

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题需要解决的问题有三个&#xff1a; 一、如何实现数字到字母的映射二、如何实现组合问题三、如何解…

基于OpenFOAM求解器二次开发

OpenFOAM&#xff08;Open Field Operation and Manipulation&#xff09;是一个开源的计算流体动力学&#xff08;CFD&#xff09;软件包。它提供了各种模拟和建模工具&#xff0c;用于研究和解决复杂的流体流动问题。 OpenFOAM提供了一个强大的求解器库&#xff0c;可以用于…

边缘计算多角色智能计量插座:用电监测和资产管理的未来智能化引擎

目前主流的智能插座涵盖了红外遥控&#xff08;控制空调和电视等带有红外标准的电器&#xff09;&#xff0c;配备着测温、测湿等仓库应用场景&#xff0c;配备了人体红外或者毫米波雷达作为联动控制&#xff0c;但是大家有没有思考一个问题&#xff0c;就是随着对接的深入&…

汽车标定技术(三)--XCP协议如何支持测量功能

目录 1. 概述 2. 测量方式 -- Poll 3. 测量方式 -- DAQ 3.1 ODT概念模型 3.2 DAQ List概念 3.3 ODT 绝对编号和相对编号 3.4 静态DAQ和动态DAQ模式 &#xff08;1&#xff09;静态DAQ &#xff08;2&#xff09;动态DAQ 4.小结 1. 概述 在该系列的首篇文章汽车标定技…

轻量封装WebGPU渲染系统示例<19>- 使用GPU Compute材质多pass实现元胞自动机之生命游戏(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/GameOfLifeMultiMaterialPass.ts 系统特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调…

苍穹外卖-day06

苍穹外卖-day06 课程内容 HttpClient微信小程序开发微信登录导入商品浏览功能代码 功能实现&#xff1a;微信登录、商品浏览 微信登录效果图&#xff1a; 商品浏览效果图&#xff1a; 1. HttpClient 1.1 介绍 HttpClient 是Apache Jakarta Common 下的子项目&#xff0c;…

Busco-真核生物为主基因组质量评估

文章目录 简介Install必须参数谱系数据集输出结果自动谱系选择结果解读完整片段化缺失 自动选择&#xff1a;多domain和污染匹配注意BUSCO报告常用脚本真核Ref 简介 Busco评估基因组质量的核心原理在于通过计算基因组的通用单拷贝标记基因的比例来估计基因组的完整性。其中两个…

SOLIDWORKS 2024新产品发布会暨SOLIDWORKS 创新日活动-硕迪科技

“达索系统SOLIDWORKS 2024新产品发布会暨SOLIDWORKS创新日” 线下发布会即将登场&#xff01;硕迪科技与达索系统携手为您奉上一场“云享未来&#xff0c;智协未来”的创新年度盛会&#xff0c;欢迎莅临&#xff01; SOLIDWORKS 2024 以更加强大的姿态亮相&#xff0c;帮助您…

下载git步骤

文章目录 导文1.软件下载2.git安装3.测试git 导文 下载git的详细步骤 1.软件下载 可以自己去网上下载&#xff0c;根据自己电脑的系统类型是多少位的&#xff0c;去下载对应的安装包。 下载地址&#xff1a;Git - Downloads 根据自己的 操作系统进行选择&#xff0c;按需选择…

学习Nginx配置

1.下载地址 官网地址&#xff1a;NGINX - 免费试用、软件下载、产品定价 (nginx-cn.net) 我这边选择NGINX 开源版 nginx: download 2.nginx的基本配置 配置文件语法 配置文件组成&#xff1a;注释行&#xff0c;指令块配置项和一系列指令配置项组成。 单个指令组成&#x…

计算机丢失mfc100.dll如何恢复,详细解析mfc100.dll文件丢失解决方法

在计算机使用过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;比如“mfc100.dll丢失”。这是因为动态链接库&#xff08;DLL&#xff09;文件是Windows操作系统的重要组成部分&#xff0c;它们包含了许多程序运行所需的函数和数据。当这些DLL文件丢失或损坏时&#x…