View 自定义 - 路径 Path

news2024/11/24 12:41:05

参考文章

一、概念

用于描述顺序 & 区域,单使用无法产生效果。

图形绘制的本质是先画点再将点连接起来,所以点与点之间是存在一个先后顺序的。图形的方向影响的是:添加图形时确定闭合顺序(各个点的记录顺序)、图形的渲染结果(是判断图形渲染的重要条件)。 

1.1 开放路径、闭合路径

1.2 判断点在图形内还是图形外

1.2.1 奇偶规则

从任意位置 P 作一条射线,对与图形的边相交的点数进行判断:

  • 若相交的点数为奇数,则认为 P 为图形内的点。
  • 若相交的点数为偶数,则认为 P 为图形外的点。

1.2.2 非零环绕数规则

从任意位置 P 作一条射线,当 P 点沿射线方向移动时,对在每个方向上穿过射线的边进行判断:

  • 每当图形的边从右到左穿过射线时 +1,从左到右穿过时 -1。
  • 若环绕数为 ≠0 则 P 为图形内的点,否则为图形外的点。

二、创建对象

Path 的起点坐标默认为 (0,0)。

  •  建全局 Path 对象,在 onDraw() 中按需修改,不要在 onDraw() 里创建,因为若 View 频繁刷新,就会频繁创建对象,拖慢刷新速度。
val path = Path()

三、设置路径

moveTo()

public void moveTo(float x, float y)

移动到新的坐标点,并作为新的起点,影响后续路径绘制。

setLastPoint()

public void setLastPoint(float dx, float dy)

移动到新的坐标点,不会改变原有起点,不影响后续路径绘制。

lineTo()

public void lineTo(float x, float y)

移动到新的坐标点,且和之前的点用直线连接。

close()

public void close()

闭合路径,将当前点和起始点连接。如果终点和起点连接后仍无法形成封闭图形则什么也不做。

先 lineTo(400,500),分别使用 moveTo(300,300) 和 setLastPoint(300,300),再 lineTo(900,800),最后 close()。 

四、重置路径

FillType 影响显示效果,数据结构影响重建速度,一般选择 reset()。

reset()

public void reset()

保留 FillType 设置,不保留原有数据结构。

rewind()

public void rewind()

不保留 FillType 设置,保留原有数据结构。

五、添加路径

5.1 基本图形

添加图形路径后会改变路径的起点。形参 dir 即方向 direction,指定绘制时是顺时针还是逆时针(CW为顺时针clockwise,CCW为逆时针counter-clockwise)。

addRect()

矩形

addRect(RectF rect, Path.Direction dir)

路径起点变为矩形的左上角顶点。

addRoundRect()

圆角矩形

addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)

addArc()

arcTo()

圆弧

public void addArc (RectF oval, float startAngle, float sweepAngle)

startAngle起始角度,sweepAngle绘制扫过的角度。

public void arcTo (RectF oval, float startAngle, float sweepAngle)

与上面方法唯一不同的是:如果圆弧的起点和最后一个坐标点不相同,就连接两个点。

public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

forceMoveTo:是否将之前路径的结束点设置为圆弧起点。设为 true 在新的起点画圆弧,不连接最后一个点与圆弧起点,即与之前路径没有交集(同第一个)。设为 false 在新的起点画圆弧,但会连接之前路径的结束点与圆弧起点,即与之前路径有交集(同第二个)。

addCircle()

圆形

addCircle(float x, float y, float radius, Path.Direction dir)

路径起点变为圆在X轴正方向最大的点 。

addOval()

椭圆形

addOval(RectF oval, Path.Direction dir) 

oval作为椭圆的外切矩形区域。

canvas.translate(350, 500)    //为了方便观察,平移坐标系
path.addRect(0, 0, 400, 400, Path.Direction.CW)    //顺时针
//path.addRect(0,0,400,400, Path.Direction.CCW)    //逆时针
canvas.drawPath(path paint)

5.1.1 矩形 addRect()

addRect(RectF rect, Path.Direction dir)

路径起点变为矩形的左上角顶点。

5.1.2 圆角矩形 addRoundRect()

addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)

5.1.3 圆弧 addArc()、arcTo()

public void addArc (RectF oval, float startAngle, float sweepAngle)

startAngle起始角度,sweepAngle绘制扫过的角度。

public void arcTo (RectF oval, float startAngle, float sweepAngle)

与上面方法唯一不同的是:如果圆弧的起点和最后一个坐标点不相同,就连接两个点。

public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

forceMoveTo:是否将之前路径的结束点设置为圆弧起点。设为 true 在新的起点画圆弧,不连接最后一个点与圆弧起点,即与之前路径没有交集(同第一个)。设为 false 在新的起点画圆弧,但会连接之前路径的结束点与圆弧起点,即与之前路径有交集(同第二个)。

5.1.4 圆形 addCircle()

addCircle(float x, float y, float radius, Path.Direction dir)

路径起点变为圆在X轴正方向最大的点 。

5.1.5 椭圆形 addOval()

addOval(RectF oval, Path.Direction dir) 

oval作为椭圆的外切矩形区域。

5.2 合并路径 addPath()

public void addPath(Path src)
public void addPath(Path src, Matrix matrix)
public void addPath(Path src, float dx, float dy)

将 src 路径添加过来,dx dy 是先偏移后再添加,matrix 是先变换后再添加。

canvas.translate(350, 500)    //为了方便观察,平移坐标系
Path pathRect = new Path()
Path  pathCircle = new Path()
pathRect.addRect(-200, -200, 200, 200, Path.Direction.CW)    // 画一个矩形路径
pathCircle.addCircle(0, 0, 100, Path.Direction.CW)    // 画一个圆形路径
pathRect.addPath(pathCircle, 0, 200)    // 将圆形路径移动(0,200),再添加到矩形路径里
canvas.drawPath(pathRect,mPaint1)    // 绘制合并后的路径

六、判断路径属性

6.1 内容是否为空 isEmpty()

public boolean isEmpty()

判断path中是否包含内容。

6.2 是否为矩形 isRect()

public boolean isRect(RectF rect)

判断path是否是一个矩形,如果是的话会将矩形信息方巾参数 rect 中。

path.lineTo(0,400)
path.lineTo(400,400)
path.lineTo(400,0)
path.lineTo(0,0)
RectF rect = new RectF()
boolean b = path.isRect(rect)    //true
//rect存放信息:
//rect.left = 0
//rect.top = 0
//rect.right = 400
//rect.bottom = 400

6.3 替换 set()

public void set(Path src)

用 src 路径替代现有路径。

path1.addRect(-200,-200,200,200, Path.Direction.CW)    //矩形路径
path2.addCircle(0,0,100, Path.Direction.CW)    //圆形路径
path1.set(path2)    //将圆形路径代替矩形路径

6.4 偏移 offset()

public void offset(float dx, float dy)

public void offset(float dx, float dy, Path dst)

偏移位置,dst 用来存储平移后的路径状态但不影响当前路径。

canvas.translate(350, 500)    //为了方便观察,平移坐标系
//path中添加一个圆形(圆心在坐标原点)
path = new Path()
path.addCircle(0, 0, 100, Path.Direction.CW)
//平移路径并存储平移后的状态
Path dst = new Path()
path.offset(400, 0, dst)    //平移
canvas.drawPath(path, mPaint1)    //绘制path
//通过dst绘制平移后的图形(红色)
mPaint1.setColor(Color.RED)
canvas.drawPath(dst,mPaint1)

七、设置路径填充颜色 xxxFillType()

getFillType()

public FillType getFillType()

设置填充规则。

setFillType()

public void setFillType(FillType ft)

获取当前填充规则。

isInverseFillType()

public boolean isInverseFillType()

判断是否是反向(INVERSE)规则。

toggleInverseFillType()

public void toggleInverseFillType()

切换填充规则(即原有规则与反向规则之间相互切换)。

  • 奇偶规则:EVEN_ODD
  • 反奇偶规则:INVERSE_EVEN_ODD
  • 非零环绕数规则:WINDING
  • 反非零环绕数规则:INVERSE_WINDING

canvas.translate(350, 500)    //为了方便观察,平移坐标系
path.addRect(-200, -200, 200, 200, Path.Direction.CW)    // 在Path中添加一个矩形
path.setFillType(Path.FillType.EVEN_ODD)    //设置Path填充模式为 奇偶规则
// path.setFillType(Path.FillType.INVERSE_EVEN_ODD)    // 反奇偶规则
canvas.drawPath(path, mPaint1)    //画出路径

 八、布尔操作 op()

 两个 Path 之间的运算,用简单的图形通过特定规则合成相对复杂的图形。

public boolean op(Path path, Op op)

对调用的 path 和传入的 path 执行布尔运算,运算结果存入到调用该方法的 path 中。

public boolean op(Path path1, Path path2, Op op)

对 path1 和 path2 执行布尔运算,运算结果存入到调用该方法的 path 中。

canvas.translate(550, 550)    //为了方便观察,平移坐标系
//画两个圆
path1.addCircle(0, 0, 100, Path.Direction.CW)
path2.addCircle(50, 0,100, Path.Direction.CW)
//取两个路径的异或集
path1.op(path2, Path.Op.XOR)
//画出路径
canvas.drawPath(path1, mPaint1)

九、贝塞尔曲线

参考文章

计算曲线的数学公式,任何一条曲线都可以用贝塞尔曲线表示。

数据点指路径的起始点和终止点。
控制点决定了路径的弯曲轨迹。根据控制点的个数,贝塞尔曲线被分为一阶贝塞尔曲线(0个控制点)、二阶贝塞尔曲线(1个控制点)、三阶贝塞尔曲线(2个控制点)等等。n+1阶贝塞尔曲线 = 有n个控制点。(1阶 = 一条直线,高阶可以拆解为多条低阶曲线)
绘制二阶贝赛尔曲线

public void quadTo(float x1, float y1, float x2, float y2)

(x1,y1)为控制点,(x2,y2)为终点

public void rQuadTo(float dx1, float dy1, float dx2, float dy2)

(x1,y1)为控制点距离起点的偏移量,(x2,y2)为终点距离起点的偏移量

绘制三阶贝赛尔曲线

public void conicTo(float x1, float y1, float x2, float y2, float weight)

(x1,y1),(x2,y2)为控制点,(x3,y3)为终点

public void rConicTo(float dx1, float dy1, float dx2, float dy2, float weight)

(x1,y1),(x2,y2)为控制点距离起点的偏移量,(x3,y3)为终点距离起点的偏移量

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArcGIS进阶:水源涵养功能分级评价操作

首先抛出水源涵养重要性评价的公式:水源涵养量降雨量-蒸散发量-地表径流量,其中地表径流量降雨量*平均地表径流系数 声明:以下数据来源于来自于牛强老师书籍(城乡规划GIS技术)。 以下给出重要性评价阈值表&#xff1…

『MySQL快速上手』-⑥-表的约束

文章目录 1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键9.综合案例 真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。 1.空…

高校为什么需要企业数据库?

随着信息化数字化的发展,企业数据库已经成为高校不可或缺的一部分。企业数据库一般整合了多维度企业数据信息。比如,艾思依托丰富的数据沉淀和领先的模型算法,打造“1N”产业大数据平台,包含“1个企业数据中心”一一涵盖全国2.4亿…

计算机提示找不到concrt140.dll怎么办,分享4个有效的修复方法

在计算机使用过程中,我们经常会遇到一些错误提示或者系统崩溃的情况。其中,concrt140.dll是一个常见的错误提示,这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题,我们需要采取一些修复措施。本文将介绍4个修复conc…

基于显著性的无人机多光谱图像语义杂草检测与分类

Saliency-Based Semantic Weeds Detection and Classification Using UAV Multispectral Imaging(2023) 摘要1、介绍2、相关工作2.1 监督学习2.2 半监督学习2.3 无监督学习 3、方法3.1 贡献3.2 PC/BC-DIM NEURAL NETWORK(预测编码/有偏竞争-分裂输入调制…

20个Python实用小技巧!来自十年老程序员的推荐~

文章目录 1.用itertools排列2.单行条件表达式3. 反转字符串4. 使用 Assert 处理异常5. 对多个输入使用拆分6. 用 zip() 转置矩阵7. 资源上下文管理器8. 下划线作为分隔符9. 尝试 f 字符串格式10.用这个技巧交换整数11. 使用 lambda 代替函数12.多次打印无循环13. 将字符串解包为…

基于机器学习的 ICU 脑血管疾病死亡风险智能预测系统

温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 重症患者或重大手术后的患者在重症监护室(ICU)内通过多种生命支持系统以维持生理功能。患者在ICU 内会被频繁持续的记录生命体征和实验室测量等多种数据。由于高频…

电大搜题——搜索难题

添加图片注释,不超过 140 字(可选) 广东开放大学是一所素有口碑的知名学府,一直致力于为广大学员提供优质的教育资源和学习支持。随着科技的不断发展,电子学习成为了现代学习的主要方式之一。为了更好地满足学员的学习…

Django(一、简介,安装与使用)

文章目录 一、Django引入1.web应用程序什么是web?web引用程序的优点web应用程序的缺点什么是web框架 2.纯手写web框架1.web框架的本质2.HTTP协议的特性:3.编写基于wsgire模块搭建web框架代码封装优化代码封装 二、Django框架的学习1.Python中的主流框架2…

Kubernetes实战(四)-部署docker harbor私有仓库

1 Docker原生私有仓库Registry 1.1 原生私有仓库Registry概述 Docker的仓库主要分两类: 私有仓库公有仓库 共有仓库只要在官方注册用户,登录即可使用。但对于仓库的使用,企业还是会有自己的专属镜像,所以私有库的搭建也是很有…

基于SSM的婚恋网站的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

前端常用的开发工具有哪些?

目录 内置管理系统的通用场景 前后端代码生成器 权限管控 开放源码 运行性能 主流数据库 写在最后 目前使用的是JNPF框架。 前端采用Vue.js,这是一种流行的前端JavaScript框架,用于构建用户界面。Vue.js具有轻量级、可扩展性强和生态系统丰富等特点&…

成集云 | 企业微信考试+活动抽奖小程序系统 | 解决方案

方案介绍 企业微信考试功能是一种基于企业微信平台的在线考试系统,可以帮助企业进行员工培训、考核、招聘等考试场景。 活动抽奖小程序系统是一种基于互联网技术的应用程序,旨在为用户提供便捷、公平的抽奖体验。它可以帮助商家或平台吸引用户关注和参…

Gorm 中的钩子和回调

一个全面的指南,利用 GORM 中的钩子和回调的力量,为定制的数据库工作流程 在数据库管理领域,定制化是打造高效和定制化工作流程的关键。GORM,这个充满活力的 Go 对象关系映射库,为开发人员提供了钩子和回调的功能&…

机器人伺服驱动控制环

伺服驱动器​的控制环,包括:位置环、速度环、电流环这三种类型。 对于伺服的控制回路,内侧控制环的响应带宽一般会是外侧控制环的5到10倍。也就是说,电流环带宽大致是速度环的5到10倍,速度环带宽则约为位置环的5到10倍…

K8S知识点(七)

(1)实战入门-Namespace kubernets:系统创建的资源在这个命名空间里 ,集群组件资源 kubrnets组件也是以pod的形式运行的 命令行方式操作 查看namespace和详情: 创建和查看和删除: 使用过配置文件操作&am…

Docker 介绍

Docker 介绍 1 介绍1.1 概述1.2 资源高效利用1.3 发展历程1.4 组件1.5 工具1.6 对环境部署和虚拟化的影响1.7 优点1.8 容器技术核心CgroupNamespaceUnionFS 2 命令信息、状态、配置info命令用于显示当前系统信息、docker容器、镜像个数、设置等信息 镜像容器资源 3 安装3.1 版本…

flashAttention是什么

flashAttention是一种attention加速计算的精确算法,它的核心有三点:tiling(分块计算),kernel合并,和重计算。

03运算符综合

03 3.1.1算数运算符 3.1.2赋值运算符 3.1.3比较(关系)运算符 3.1.4逻辑运算符 3.1.5位运算符 3.2运算符的优先级 3.3条件表达式

IP地址冲突解决办法

在计算机网络中,每个设备都需要一个唯一的IP地址来与其他设备进行通信。然而,有时候会出现IP地址冲突的情况即多个设备使用了相同的IP地址。这种冲突会导致网络连接问题,因此需要及时解决。 IP地址查询:IP66_ip归属地在线查询_免费…