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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用数据分析,识别设备异常

设备健康监测系统在工业领域中扮演着至关重要的角色&#xff0c;它能够帮助企业及时发现设备异常&#xff0c;预防故障&#xff0c;提高设备使用寿命和生产效率。而异常诊断技术则是设备健康监测系统中的核心部分&#xff0c;能够实现对设备异常情况的准确判断。根据设备状态数…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步&#xff1a; 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件&#xff0c;它提供了一个可视化的表格控件&#xff0c;允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

RHCSA --- Linux命令替换

命令替换 把命令中某个子命令替换为其执行结果 $() echo "The current directory is $(pwd)." touch ./file$(date %H-%M-%S).txt 以文件创建时间并以相应格式命名文件 date 显示时间 echo "The current direct…

C++二分算法:水位上升的泳池中游泳

涉及知识点 二分查找 并集查找或BFS。 题目 在一个 n x n 的整数矩阵 grid 中&#xff0c;每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。 当开始下雨时&#xff0c;在时间为 t 时&#xff0c;水池中的水位为 t 。你可以从一个平台游向四周相邻的任意一个平台&…

Oracle Unifier 22.12 ~ 23.10 功能改进清单表

序言 时隔近一年&#xff0c;Oracle Unifier 22还没握熟&#xff0c;新版本23便已迭代到23.10&#xff0c;根据甲骨文常规的发布规律&#xff0c;相信不久之后便会正式迎来正式本地版V23&#xff0c;了解Unfier的朋友或许知晓&#xff0c;本地版是云版迭代一年后的版本&#x…

SSM 线上知识竞赛系统-计算机毕设 附源码 27170

SSM线上知识竞赛系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#…

Go进阶之rpc和grpc

文章目录 Go环境安装1&#xff09;windows2&#xff09;linux go语言编码规范1.1 包名&#xff1a;package1.2 ⽂件名1.3 结构体命名1.4 接⼝命名1.5 变量命名1.6 常量命名2.1 包注释2.2 结构&#xff08;接⼝&#xff09;注释2.3 函数&#xff08;⽅法&#xff09;注释2.4 代码…

Flink架构

1、Apache Flink集群的核心架构&#xff1a; 1、client&#xff08;作业客户端&#xff09;&#xff1a;提交任务的地方叫做客户端 2、JobManager&#xff08;作业管理器&#xff09;&#xff1a;作用是用于管理集群中任务 3、TaskManager&#xff08;任务管理器&#xff09;&a…

内网可达网段探测netspy- Mac环境

netspy是一款快速探测内网可达网段工具 当我们进入内网后想要扩大战果&#xff0c;那我们可能首先想知道当前主机能通哪些内网段。 netspy正是一款应用而生的小工具&#xff0c;体积较小&#xff0c;速度极快&#xff0c;支持跨平台&#xff0c;支持多种协议探测&#xff0c;…

ZZ308 物联网应用与服务赛题第E套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 &#xff08;E卷&#xff09; 赛位号&#xff1a;______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等&#xff1b; 2.竞赛任务中所使用的…

财报解读:抢滩“睡眠经济”,麒盛科技如何制胜市场?

现代市场经济理论的鼻祖亚当斯密曾说&#xff0c;有需求就有市场&#xff0c;有市场才有发展。 调查研究显示&#xff0c;我国超3亿人存在睡眠障碍&#xff0c;其中超3/4的人晚11点以后入睡&#xff0c;近1/3的人熬到凌晨1点以后才能入睡。针对“睡个好觉”需求的“睡眠经济”…

Qt开发流程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

11-08 周三 图解机器学习之实现逻辑异或,理解输出层误差和隐藏层误差项和动量因子

11-08 周三 图解机器学习之实现逻辑异或&#xff0c;理解输出层误差和隐藏层误差项 时间版本修改人描述2023年11月8日14:36:36V0.1宋全恒新建文档 简介 最近笔者完成了《图解机器学习》这本书的阅读&#xff0c;由于最近深度学习网络大行其是&#xff0c;所以也想要好好的弄清…

【Unity】零基础实现塔防游戏中敌人沿固定路径移动的功能

目录 场景搭建 烘焙(Bake) 敌人动作控制 脚本实现 我们知道&#xff0c;在一些塔防小游戏中&#xff0c;敌人往往会沿着给定的一条路径移动&#xff0c;我们在条路的路边会布置防御设施&#xff0c;攻击消灭敌人&#xff0c;阻止敌人到达终点。 场景搭建 我们首先新建一个…

Leetcode 第 369 场周赛题解

Leetcode 第 369 场周赛题解 Leetcode 第 369 场周赛题解题目1&#xff1a;2917. 找出数组中的 K-or 值思路代码复杂度分析 题目2&#xff1a;2918. 数组的最小相等和思路代码复杂度分析 题目3&#xff1a;2919. 使数组变美的最小增量运算数思路代码复杂度分析 题目4&#xff1…

Git 行结束符:LF will be replaced by CRLF the next time Git touches it问题解决指南

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

ruoyi-vue前端数据字典值引用与回显(列表中回显,多选框回显)

1. 列表中回显&#xff1a; 代码&#xff1a; <el-table v-if"refreshTable" v-loading"loading" :data"deptList" row-key"deptId" :default-expand-all"isExpandAll" :tree-props"{children: children, hasChil…

BP神经网络的数据分类——语音特征信号分类

大家好&#xff0c;我是带我去滑雪&#xff01; BP神经网络&#xff0c;也称为反向传播神经网络&#xff0c;是一种常用于分类和回归任务的人工神经网络&#xff08;ANN&#xff09;类型。它是一种前馈神经网络&#xff0c;通常包括输入层、一个或多个隐藏层和输出层。BP神经网…

虚幻C+++基础 day2

角色移动与视角控制 Character类与相关API 创建Character子类MainPlayer.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "GameFramework/Character.h" #include &q…

遭受网络攻击泄露了101GB数据

臭名昭著的BlackCat/ALPHV勒索软件团伙声称对另一个组织发起了攻击。今天轮到意大利-法国科西嘉-费里斯公司发现自己正在与勒索软件作斗争。 BlackCat 在其数据泄露网站上报告称&#xff0c;该公司是网络攻击的受害者&#xff0c;并发布了从该公司 IT 基础设施中泄露的一系列样…