自定义View——Path 路径

介绍

Path类 可以绘制由直线段,二次曲线和三次曲线组成的复合(多轮廓)几何路径。它的用武之地也非常多, 它可以用于canvas.drawPath()绘制奇形怪状,可以是填充或描边(基于绘制的样式),也可以用于剪裁或在路径上绘制文本(在Canvas 画布使用有介绍)。

该文章主要参考:https://juejin.im/post/5962a3746fb9a06ba2687226

API使用

官网API : https://developer.android.google.cn/reference/android/graphics/Path.html

1. 在 canvas.drawPath()的使用

1.1 直线路径

相关的API有:

lineTo (float x2, float y2) :直线的结束点,又是下一次绘制直线路径的开始点。可以连续执行该方法

rLineTo(float dx, float dy) :与lineTo ()类似,只是坐标的相对位置不一样,该方法的相对位置是:相对上一次的绘制的结束点。还有:rMoveTo()、rQuadTo()多是类似

moveTo (float x1, float y1):直线的开始点;即将直线路径的绘制开始点定在(x1,y1)的位置;

setLastPoint(float dx, float dy) :设置路径的最后一个点,简单来讲改变结束点的位置。

close () :如果连续画了几条直线,但没有形成闭环,调用Close()会将路径首尾点连接起来,形成闭环;

但是,有时并不是所有的子图形都需要使用 close() 来封闭。当需要填充图形时(即 Paint.Style 为 FILL 或 FILL_AND_STROKE),Path 会自动封闭子图形。

注意:如果只是画一条线时,这里的画笔需要设置为描边,不然什么也没有显示

1.2 几何图形路径

Path很多addXxx( )、arcTo的方法,下面就逐一介绍。
但是,这里没有过多的啰嗦每个参数,因为和 Canvas 的使用类似。如果不熟悉Canvas 的使用,可以点这里:
自定义View——Canvas 画布

添加矩形
addRect(RectF rect, Path.Direction dir)
addRect(float left, float top, float right, float bottom, Path.Direction dir)
添加圆角矩形

每个圆角多一样:

addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)

自定义每个圆角:

addRoundRect(RectF rect, float[] radii, Path.Direction dir)
addRoundRect(float left, float top, float right, float bottom, float[] radii, Path.Direction dir)

参数:
radii:数值集合,必须提供8个数值,每个2数值 [x, y] 一组,绘制顺序是从左上角,右上角,右下角,左下角

添加圆
addCircle(float x, float y, float radius, Path.Direction dir)
添加椭圆
addOval(RectF oval, Path.Direction dir)
addOval(float left, float top, float right, float bottom, Path.Direction dir)

以上的路径绘制,大部分和Canvas直接绘制基本图形大致一样,这里需要说明的就是参数Path.Direction

Path.Direction指的是绘制路劲的方向,有2种:

Path.Direction.CW:顺时针方向绘制(clockwise)
Path.Direction.CCW:逆时针方向绘制 (counter-clockwise)

没毛病,你画圆的时候,可以左三圈,也可以有三圈,方向就不一样了。但是,你会看到 圆还是那个圆,从效果上没什么区别。是的,在普通情况,这个参数没什么鸟用。

问题1:那这个参数没啥用,而且绘制又和Canvan绘制那么类似,那还用他干嘛?

  1. 如果是单独画一个基本图形,可以直接使用Canvan来绘制;
  2. 如果是不间断的绘制多个基本图形,或者不规则图形,可以使用Path类;
  3. 如果需要填充图形 (Paint.Style 为 FILL 或 FILL_AND_STROKE) ,并且图形出现自相交时,用于判断填充范围,可以使用Path.Direction参数
添加圆弧
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)
addArc(RectF oval, float startAngle, float sweepAngle) 

和Canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 比起来,少了参数 useCenter。因为 Path.addArc方法只用来画弧形而不画扇形。

这里,绘制圆弧还有一些方法:

arcTo(RectF oval, float startAngle, float sweepAngle)
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)

同样没有参数 useCenter,但这里多一个参数:
forceMoveTo 是否执行moveTo,看图一目了然:

图片描述

问题2:arcTo(),addArc()多可以绘制圆弧,区别在哪里?

看参数就知道,主要区别就是参数forceMoveTo ,addArc() 默认forceMoveTo 是true,没有带forceMoveTo 的arcTo()默认是false。而带有该参数的arcTo()可自定义。嗯,就是那么的简单。

1.3 其他API

添加路径

addPath(Path src)

将路径src添加到当前路径Path,有集合的意思

addPath(Path src, float dx, float dy)

将路径src移动(dx,dy)后,再添加到当前路径Path

addPath(Path src, Matrix matrix)

将路径src经过matrix变换之后,再添加到当前路径Path

reset()

路径重置

isRect(RectF rect)

当前的路径path是否组成一个矩形,如果是,则赋值给rect

set(Path src)

清除之前的路径path,将src赋给当前路径path

offset(float dx, float dy)

移动当前的路径

offset(float dx, float dy, Path dst)

如果传入null,实现和offset(dx,  dy)一样;
如果传入path对象,那么执行offset没有效果,将移动效果赋给dst。

2. 填充的使用

前面说到绘制基本图形有个参数:Path.Direction ,在填充的时候就用到了

setFillType(Path.FillType ft) 设置填充模式

getFillType() 获取填充模式

isInverseFillType() 是否是“反“填充模式

下面详细解析以上方法:

Path的填充模式有4种,即FillType 有4个值可以选择:

FillType说明
WINDING (默认值)非零环绕数原则
INVERSE_WINDING反非零环绕数原则
EVEN_ODD奇偶原则
INVERSE_EVEN_ODD反奇偶原则

后面2种原则带有“INVERSE_”前缀,即填充的部分与上面2种相反(反色),只要弄懂前面2种,那么后面2种自然就知道了。

这里需要注意的是:


对于填充来说,在图形外部是不被填充,在图形内部是被填充的。


EVEN_ODD 奇偶原则 (与图形绘制方向无关)
在任意位置一点,作一根不经过顶点的射线,计算穿过平面图形的边数,如果是奇数,则该点在图形内部;如果是偶数,则该点在图形外部。

图片描述

WINDING 非零环绕数原则 (与绘制方向有关)

(网上很多对方向的解释是从左到右,感觉很模糊。直接按照时钟方向比较清晰)
在任意位置一点,作一根不经过顶点的射线,如果平面图形顺时针方向穿过射线,则+1;如果平面图形逆时针方向穿过射线,则-1;最终和数如果是 非零则是内部点,反之是外部点。

图片描述

以上2种方式,总结有以下效果图:

好了,现在大约知道这2中模式了,另外2种“INVERSE”主要把效果反过来即可,不多说。

布尔操作

什么是布尔操作?与集合运算很相似。对于多个路径path,可以取它们交集、并集、差集等,然后组成不同的图像。

首先看这个2个方法:

Path resultPath;

op(Path path, Path.Op op):对 resultPathpath 执行布尔运算,运算方式由第二个参数指定,运算结果存入到 resultPath 中。

op(Path path1, Path path2, Path.Op op) : 对 path1path2 执行布尔运算,运算方式由第三个参数指定,运算结果存入到 resultPath 中。

参数:
path1:第一个路径(用于差异、被减数)
path2:第二个路径(用于差异,减少)
op:布尔运算的模式,有5种可选择。下面会介绍

对于不同布尔运算,总结有以下效果图:

图片描述

布尔操作,看着还是很直观的,只要学过集合,一看便会了。

总结

这里用法,应该还有 贝塞尔曲线 的应用,还未能了解透彻,暂时先不介绍了。


欢迎点赞

参考:

https://juejin.im/post/5962a3746fb9a06ba2687226

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值